]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'master' into upstream
authorJeff Garzik <jeff@garzik.org>
Wed, 27 Sep 2006 22:16:47 +0000 (18:16 -0400)
committerJeff Garzik <jeff@garzik.org>
Wed, 27 Sep 2006 22:16:47 +0000 (18:16 -0400)
1466 files changed:
Documentation/ABI/removed/devfs [moved from Documentation/ABI/obsolete/devfs with 72% similarity]
Documentation/ABI/testing/sysfs-power [new file with mode: 0644]
Documentation/DocBook/usb.tmpl
Documentation/HOWTO
Documentation/devices.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/proc.txt
Documentation/i2c/busses/i2c-viapro
Documentation/i2c/i2c-stub
Documentation/kbuild/makefiles.txt
Documentation/kernel-parameters.txt
Documentation/networking/bonding.txt
Documentation/nommu-mmap.txt
Documentation/pcieaer-howto.txt [new file with mode: 0644]
Documentation/power/devices.txt
Documentation/sh/new-machine.txt
Documentation/sh/register-banks.txt [new file with mode: 0644]
Documentation/usb/error-codes.txt
Documentation/usb/usb-serial.txt
Documentation/x86_64/boot-options.txt
Documentation/x86_64/kernel-stacks [new file with mode: 0644]
MAINTAINERS
Makefile
arch/arm/mach-pxa/corgi.c
arch/arm/plat-omap/usb.c
arch/avr32/mm/tlb.c
arch/i386/Kconfig
arch/i386/Makefile
arch/i386/boot/edd.S
arch/i386/boot/setup.S
arch/i386/defconfig
arch/i386/kernel/Makefile
arch/i386/kernel/acpi/Makefile
arch/i386/kernel/acpi/boot.c
arch/i386/kernel/acpi/earlyquirk.c
arch/i386/kernel/apic.c
arch/i386/kernel/cpu/amd.c
arch/i386/kernel/cpu/centaur.c
arch/i386/kernel/cpu/common.c
arch/i386/kernel/cpu/cpu.h
arch/i386/kernel/cpu/cyrix.c
arch/i386/kernel/cpu/intel.c
arch/i386/kernel/cpu/mcheck/Makefile
arch/i386/kernel/cpu/mcheck/p4.c
arch/i386/kernel/cpu/mcheck/therm_throt.c [new file with mode: 0644]
arch/i386/kernel/cpu/nexgen.c
arch/i386/kernel/cpu/proc.c
arch/i386/kernel/cpu/rise.c
arch/i386/kernel/cpu/transmeta.c
arch/i386/kernel/cpu/umc.c
arch/i386/kernel/crash.c
arch/i386/kernel/entry.S
arch/i386/kernel/head.S
arch/i386/kernel/i8259.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/machine_kexec.c
arch/i386/kernel/mca.c
arch/i386/kernel/microcode.c
arch/i386/kernel/mpparse.c
arch/i386/kernel/nmi.c
arch/i386/kernel/process.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/relocate_kernel.S
arch/i386/kernel/semaphore.c [deleted file]
arch/i386/kernel/setup.c
arch/i386/kernel/smpboot.c
arch/i386/kernel/srat.c
arch/i386/kernel/stacktrace.c [deleted file]
arch/i386/kernel/syscall_table.S
arch/i386/kernel/time.c
arch/i386/kernel/topology.c
arch/i386/kernel/traps.c
arch/i386/kernel/tsc.c
arch/i386/lib/Makefile
arch/i386/lib/semaphore.S [new file with mode: 0644]
arch/i386/mach-generic/bigsmp.c
arch/i386/mach-generic/es7000.c
arch/i386/mach-generic/probe.c
arch/i386/mach-generic/summit.c
arch/i386/mm/discontig.c
arch/i386/mm/extable.c
arch/i386/mm/fault.c
arch/i386/mm/highmem.c
arch/i386/mm/init.c
arch/i386/oprofile/nmi_int.c
arch/i386/oprofile/nmi_timer_int.c
arch/i386/oprofile/op_model_athlon.c
arch/i386/oprofile/op_model_p4.c
arch/i386/oprofile/op_model_ppro.c
arch/i386/oprofile/op_x86_model.h
arch/i386/pci/Makefile
arch/i386/pci/common.c
arch/i386/pci/direct.c
arch/i386/pci/early.c [new file with mode: 0644]
arch/i386/pci/init.c
arch/i386/pci/mmconfig.c
arch/i386/pci/pci.h
arch/ia64/Kconfig
arch/ia64/ia32/sys_ia32.c
arch/ia64/kernel/Makefile
arch/ia64/kernel/entry.S
arch/ia64/kernel/esi.c [new file with mode: 0644]
arch/ia64/kernel/esi_stub.S [new file with mode: 0644]
arch/ia64/kernel/ia64_ksyms.c
arch/ia64/kernel/kprobes.c
arch/ia64/kernel/mca.c
arch/ia64/kernel/mca_asm.S
arch/ia64/kernel/mca_drv.c
arch/ia64/kernel/mca_drv.h
arch/ia64/kernel/perfmon.c
arch/ia64/kernel/salinfo.c
arch/ia64/kernel/setup.c
arch/ia64/kernel/smpboot.c
arch/ia64/kernel/topology.c
arch/ia64/kernel/vmlinux.lds.S
arch/ia64/mm/contig.c
arch/ia64/mm/discontig.c
arch/ia64/mm/init.c
arch/ia64/pci/pci.c
arch/ia64/sn/kernel/bte.c
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/au1000/db1x00/Makefile
arch/mips/au1000/db1x00/mirage_ts.c [deleted file]
arch/mips/basler/excite/excite_device.c
arch/mips/configs/atlas_defconfig
arch/mips/configs/bigsur_defconfig
arch/mips/configs/capcella_defconfig
arch/mips/configs/cobalt_defconfig
arch/mips/configs/db1000_defconfig
arch/mips/configs/db1100_defconfig
arch/mips/configs/db1200_defconfig
arch/mips/configs/db1500_defconfig
arch/mips/configs/db1550_defconfig
arch/mips/configs/ddb5477_defconfig
arch/mips/configs/decstation_defconfig
arch/mips/configs/e55_defconfig
arch/mips/configs/emma2rh_defconfig
arch/mips/configs/ev64120_defconfig
arch/mips/configs/excite_defconfig
arch/mips/configs/ip22_defconfig
arch/mips/configs/ip27_defconfig
arch/mips/configs/ip32_defconfig
arch/mips/configs/it8172_defconfig
arch/mips/configs/ivr_defconfig
arch/mips/configs/jaguar-atx_defconfig
arch/mips/configs/jmr3927_defconfig
arch/mips/configs/lasat200_defconfig
arch/mips/configs/malta_defconfig
arch/mips/configs/mipssim_defconfig
arch/mips/configs/mpc30x_defconfig
arch/mips/configs/ocelot_3_defconfig
arch/mips/configs/ocelot_c_defconfig
arch/mips/configs/ocelot_defconfig
arch/mips/configs/ocelot_g_defconfig
arch/mips/configs/pb1100_defconfig
arch/mips/configs/pb1500_defconfig
arch/mips/configs/pb1550_defconfig
arch/mips/configs/pnx8550-jbs_defconfig
arch/mips/configs/pnx8550-v2pci_defconfig
arch/mips/configs/qemu_defconfig
arch/mips/configs/rbhma4500_defconfig
arch/mips/configs/rm200_defconfig
arch/mips/configs/sb1250-swarm_defconfig
arch/mips/configs/sead_defconfig
arch/mips/configs/tb0226_defconfig
arch/mips/configs/tb0229_defconfig
arch/mips/configs/tb0287_defconfig
arch/mips/configs/workpad_defconfig
arch/mips/configs/wrppmc_defconfig
arch/mips/configs/yosemite_defconfig
arch/mips/defconfig
arch/mips/galileo-boards/ev96100/Makefile [deleted file]
arch/mips/galileo-boards/ev96100/init.c [deleted file]
arch/mips/galileo-boards/ev96100/irq.c [deleted file]
arch/mips/galileo-boards/ev96100/puts.c [deleted file]
arch/mips/galileo-boards/ev96100/reset.c [deleted file]
arch/mips/galileo-boards/ev96100/setup.c [deleted file]
arch/mips/galileo-boards/ev96100/time.c [deleted file]
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/irixsig.c
arch/mips/kernel/linux32.c
arch/mips/kernel/process.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/smtc-asm.S
arch/mips/kernel/syscall.c
arch/mips/kernel/traps.c
arch/mips/kernel/vpe.c
arch/mips/mips-boards/atlas/atlas_int.c
arch/mips/mips-boards/atlas/atlas_setup.c
arch/mips/mips-boards/generic/time.c
arch/mips/mm/c-r3k.c
arch/mips/mm/c-r4k.c
arch/mips/mm/c-sb1.c
arch/mips/mm/c-tx39.c
arch/mips/mm/cache.c
arch/mips/mm/fault.c
arch/mips/mm/tlb-r4k.c
arch/mips/pci/Makefile
arch/mips/pci/fixup-atlas.c
arch/mips/pci/fixup-ev96100.c [deleted file]
arch/mips/pci/ops-au1000.c
arch/mips/pci/ops-gt96100.c [deleted file]
arch/mips/pci/pci-ev96100.c [deleted file]
arch/mips/pci/pci-ip27.c
arch/mips/sibyte/bcm1480/irq.c
arch/mips/sibyte/sb1250/irq.c
arch/powerpc/Kconfig
arch/powerpc/kernel/sys_ppc32.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/pseries/hvCall_inst.c
arch/powerpc/sysdev/mpic.c
arch/ppc/Kconfig
arch/ppc/mm/init.c
arch/s390/hypfs/inode.c
arch/s390/kernel/compat_linux.c
arch/s390/kernel/debug.c
arch/s390/kernel/stacktrace.c
arch/sh/Kconfig
arch/sh/Kconfig.debug
arch/sh/Makefile
arch/sh/boards/adx/Makefile [deleted file]
arch/sh/boards/adx/irq.c [deleted file]
arch/sh/boards/adx/setup.c [deleted file]
arch/sh/boards/bigsur/irq.c
arch/sh/boards/bigsur/setup.c
arch/sh/boards/cat68701/Makefile [deleted file]
arch/sh/boards/cat68701/irq.c [deleted file]
arch/sh/boards/cat68701/setup.c [deleted file]
arch/sh/boards/cqreek/Makefile [deleted file]
arch/sh/boards/cqreek/irq.c [deleted file]
arch/sh/boards/cqreek/setup.c [deleted file]
arch/sh/boards/dmida/Makefile [deleted file]
arch/sh/boards/dmida/mach.c [deleted file]
arch/sh/boards/dreamcast/irq.c
arch/sh/boards/dreamcast/rtc.c
arch/sh/boards/dreamcast/setup.c
arch/sh/boards/ec3104/setup.c
arch/sh/boards/harp/Makefile [deleted file]
arch/sh/boards/harp/irq.c [deleted file]
arch/sh/boards/harp/led.c [deleted file]
arch/sh/boards/harp/mach.c [deleted file]
arch/sh/boards/harp/pcidma.c [deleted file]
arch/sh/boards/harp/setup.c [deleted file]
arch/sh/boards/hp6xx/Makefile
arch/sh/boards/hp6xx/hp6xx_apm.c [new file with mode: 0644]
arch/sh/boards/hp6xx/pm.c [new file with mode: 0644]
arch/sh/boards/hp6xx/pm_wakeup.S [new file with mode: 0644]
arch/sh/boards/hp6xx/setup.c
arch/sh/boards/landisk/Makefile [new file with mode: 0644]
arch/sh/boards/landisk/io.c [new file with mode: 0644]
arch/sh/boards/landisk/irq.c [new file with mode: 0644]
arch/sh/boards/landisk/landisk_pwb.c [new file with mode: 0644]
arch/sh/boards/landisk/rtc.c [new file with mode: 0644]
arch/sh/boards/landisk/setup.c [new file with mode: 0644]
arch/sh/boards/mpc1211/rtc.c
arch/sh/boards/mpc1211/setup.c
arch/sh/boards/overdrive/Makefile [deleted file]
arch/sh/boards/overdrive/fpga.c [deleted file]
arch/sh/boards/overdrive/galileo.c [deleted file]
arch/sh/boards/overdrive/io.c [deleted file]
arch/sh/boards/overdrive/irq.c [deleted file]
arch/sh/boards/overdrive/led.c [deleted file]
arch/sh/boards/overdrive/mach.c [deleted file]
arch/sh/boards/overdrive/pcidma.c [deleted file]
arch/sh/boards/overdrive/setup.c [deleted file]
arch/sh/boards/renesas/edosk7705/Makefile
arch/sh/boards/renesas/edosk7705/setup.c
arch/sh/boards/renesas/hs7751rvoip/Kconfig [new file with mode: 0644]
arch/sh/boards/renesas/hs7751rvoip/Makefile
arch/sh/boards/renesas/hs7751rvoip/io.c
arch/sh/boards/renesas/hs7751rvoip/irq.c
arch/sh/boards/renesas/hs7751rvoip/led.c [deleted file]
arch/sh/boards/renesas/hs7751rvoip/mach.c [deleted file]
arch/sh/boards/renesas/hs7751rvoip/setup.c
arch/sh/boards/renesas/r7780rp/Kconfig [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/Makefile [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/io.c [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/irq.c [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/led.c [new file with mode: 0644]
arch/sh/boards/renesas/r7780rp/setup.c [new file with mode: 0644]
arch/sh/boards/renesas/rts7751r2d/Kconfig [new file with mode: 0644]
arch/sh/boards/renesas/rts7751r2d/Makefile
arch/sh/boards/renesas/rts7751r2d/io.c
arch/sh/boards/renesas/rts7751r2d/irq.c
arch/sh/boards/renesas/rts7751r2d/led.c
arch/sh/boards/renesas/rts7751r2d/mach.c [deleted file]
arch/sh/boards/renesas/rts7751r2d/setup.c
arch/sh/boards/renesas/sh7710voipgw/Makefile [new file with mode: 0644]
arch/sh/boards/renesas/sh7710voipgw/setup.c [new file with mode: 0644]
arch/sh/boards/renesas/systemh/io.c
arch/sh/boards/renesas/systemh/irq.c
arch/sh/boards/renesas/systemh/setup.c
arch/sh/boards/saturn/setup.c
arch/sh/boards/se/7300/io.c
arch/sh/boards/se/7300/irq.c
arch/sh/boards/se/7300/led.c
arch/sh/boards/se/7300/setup.c
arch/sh/boards/se/73180/io.c
arch/sh/boards/se/73180/irq.c
arch/sh/boards/se/73180/led.c
arch/sh/boards/se/73180/setup.c
arch/sh/boards/se/7343/Makefile [new file with mode: 0644]
arch/sh/boards/se/7343/io.c [new file with mode: 0644]
arch/sh/boards/se/7343/irq.c [new file with mode: 0644]
arch/sh/boards/se/7343/led.c [new file with mode: 0644]
arch/sh/boards/se/7343/setup.c [new file with mode: 0644]
arch/sh/boards/se/770x/Makefile
arch/sh/boards/se/770x/io.c
arch/sh/boards/se/770x/irq.c
arch/sh/boards/se/770x/led.c
arch/sh/boards/se/770x/mach.c [deleted file]
arch/sh/boards/se/770x/setup.c
arch/sh/boards/se/7751/Makefile
arch/sh/boards/se/7751/io.c
arch/sh/boards/se/7751/irq.c
arch/sh/boards/se/7751/led.c
arch/sh/boards/se/7751/mach.c [deleted file]
arch/sh/boards/se/7751/setup.c
arch/sh/boards/sh03/rtc.c
arch/sh/boards/sh03/setup.c
arch/sh/boards/sh2000/Makefile [deleted file]
arch/sh/boards/sh2000/setup.c [deleted file]
arch/sh/boards/shmin/Makefile [new file with mode: 0644]
arch/sh/boards/shmin/setup.c [new file with mode: 0644]
arch/sh/boards/snapgear/io.c
arch/sh/boards/snapgear/rtc.c
arch/sh/boards/snapgear/setup.c
arch/sh/boards/superh/microdev/irq.c
arch/sh/boards/superh/microdev/setup.c
arch/sh/boards/titan/Makefile [new file with mode: 0644]
arch/sh/boards/titan/io.c [new file with mode: 0644]
arch/sh/boards/titan/setup.c [new file with mode: 0644]
arch/sh/boards/unknown/setup.c
arch/sh/boot/compressed/Makefile
arch/sh/cchips/Kconfig
arch/sh/cchips/hd6446x/hd64461/io.c
arch/sh/cchips/hd6446x/hd64461/setup.c
arch/sh/cchips/hd6446x/hd64465/setup.c
arch/sh/cchips/voyagergx/irq.c
arch/sh/cchips/voyagergx/setup.c
arch/sh/configs/landisk_defconfig [new file with mode: 0644]
arch/sh/configs/r7780rp_defconfig [new file with mode: 0644]
arch/sh/configs/se73180_defconfig
arch/sh/configs/se7343_defconfig [new file with mode: 0644]
arch/sh/configs/sh7710voipgw_defconfig [new file with mode: 0644]
arch/sh/configs/shmin_defconfig [moved from arch/mips/configs/ev96100_defconfig with 50% similarity]
arch/sh/configs/titan_defconfig [new file with mode: 0644]
arch/sh/drivers/dma/Kconfig
arch/sh/drivers/dma/dma-g2.c
arch/sh/drivers/dma/dma-pvr2.c
arch/sh/drivers/dma/dma-sh.c
arch/sh/drivers/pci/Makefile
arch/sh/drivers/pci/fixups-dreamcast.c
arch/sh/drivers/pci/fixups-r7780rp.c [new file with mode: 0644]
arch/sh/drivers/pci/fixups-rts7751r2d.c
arch/sh/drivers/pci/fixups-sh03.c
arch/sh/drivers/pci/ops-bigsur.c
arch/sh/drivers/pci/ops-landisk.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-r7780rp.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-rts7751r2d.c
arch/sh/drivers/pci/ops-sh4.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-snapgear.c
arch/sh/drivers/pci/ops-titan.c [new file with mode: 0644]
arch/sh/drivers/pci/pci-auto.c
arch/sh/drivers/pci/pci-sh4.h [new file with mode: 0644]
arch/sh/drivers/pci/pci-sh7751.c
arch/sh/drivers/pci/pci-sh7751.h
arch/sh/drivers/pci/pci-sh7780.c [new file with mode: 0644]
arch/sh/drivers/pci/pci-sh7780.h [new file with mode: 0644]
arch/sh/drivers/pci/pci-st40.c
arch/sh/drivers/pci/pci.c
arch/sh/kernel/Makefile
arch/sh/kernel/apm.c [new file with mode: 0644]
arch/sh/kernel/cf-enabler.c
arch/sh/kernel/cpu/Makefile
arch/sh/kernel/cpu/clock.c
arch/sh/kernel/cpu/init.c
arch/sh/kernel/cpu/irq/Makefile
arch/sh/kernel/cpu/irq/intc2.c
arch/sh/kernel/cpu/irq/ipr.c
arch/sh/kernel/cpu/irq/maskreg.c [moved from arch/sh/boards/adx/irq_maskreg.c with 63% similarity]
arch/sh/kernel/cpu/irq/pint.c
arch/sh/kernel/cpu/rtc.c [deleted file]
arch/sh/kernel/cpu/sh3/Makefile
arch/sh/kernel/cpu/sh3/clock-sh7706.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/ex.S
arch/sh/kernel/cpu/sh3/probe.c
arch/sh/kernel/cpu/sh3/setup-sh7300.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/setup-sh7705.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/setup-sh7708.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/setup-sh7709.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/setup-sh7710.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/Makefile
arch/sh/kernel/cpu/sh4/ex.S
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/cpu/sh4/setup-sh4-202.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh73180.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh7343.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh7750.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh7760.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh7770.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/setup-sh7780.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/sq.c
arch/sh/kernel/early_printk.c
arch/sh/kernel/entry.S
arch/sh/kernel/head.S
arch/sh/kernel/io.c
arch/sh/kernel/irq.c
arch/sh/kernel/kgdb_stub.c
arch/sh/kernel/machine_kexec.c
arch/sh/kernel/pm.c [new file with mode: 0644]
arch/sh/kernel/process.c
arch/sh/kernel/ptrace.c
arch/sh/kernel/semaphore.c
arch/sh/kernel/setup.c
arch/sh/kernel/sh_ksyms.c
arch/sh/kernel/signal.c
arch/sh/kernel/sys_sh.c
arch/sh/kernel/syscalls.S [new file with mode: 0644]
arch/sh/kernel/time.c
arch/sh/kernel/timers/timer-tmu.c
arch/sh/kernel/traps.c
arch/sh/kernel/vmlinux.lds.S
arch/sh/kernel/vsyscall/Makefile [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall-note.S [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall-sigreturn.S [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall-syscall.S [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall-trapa.S [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall.c [new file with mode: 0644]
arch/sh/kernel/vsyscall/vsyscall.lds.S [new file with mode: 0644]
arch/sh/lib/checksum.S
arch/sh/lib/memcpy-sh4.S
arch/sh/lib/memset.S
arch/sh/math-emu/Makefile [new file with mode: 0644]
arch/sh/math-emu/math.c [new file with mode: 0644]
arch/sh/math-emu/sfp-util.h [new file with mode: 0644]
arch/sh/mm/Kconfig
arch/sh/mm/Makefile
arch/sh/mm/cache-debugfs.c [new file with mode: 0644]
arch/sh/mm/cache-sh4.c
arch/sh/mm/cache-sh7705.c
arch/sh/mm/clear_page.S
arch/sh/mm/consistent.c
arch/sh/mm/fault.c
arch/sh/mm/hugetlbpage.c
arch/sh/mm/init.c
arch/sh/mm/ioremap.c
arch/sh/mm/pg-nommu.c
arch/sh/mm/pg-sh4.c
arch/sh/mm/pmb.c [new file with mode: 0644]
arch/sh/mm/tlb-flush.c [new file with mode: 0644]
arch/sh/mm/tlb-sh4.c
arch/sh/oprofile/Makefile
arch/sh/tools/mach-types
arch/sparc64/defconfig
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/mm/init.c
arch/um/Makefile-x86_64
arch/um/drivers/chan_kern.c
arch/um/drivers/daemon.h
arch/um/drivers/daemon_kern.c
arch/um/drivers/daemon_user.c
arch/um/drivers/fd.c
arch/um/drivers/hostaudio_kern.c
arch/um/drivers/line.c
arch/um/drivers/mcast.h
arch/um/drivers/mcast_kern.c
arch/um/drivers/mcast_user.c
arch/um/drivers/mmapper_kern.c
arch/um/drivers/net_kern.c
arch/um/drivers/null.c
arch/um/drivers/pcap_kern.c
arch/um/drivers/pcap_user.c
arch/um/drivers/port_user.c
arch/um/drivers/pty.c
arch/um/drivers/random.c
arch/um/drivers/slip.h
arch/um/drivers/slip_kern.c
arch/um/drivers/slip_user.c
arch/um/drivers/slirp.h
arch/um/drivers/slirp_kern.c
arch/um/drivers/slirp_user.c
arch/um/drivers/ssl.c
arch/um/drivers/stdio_console.c
arch/um/drivers/tty.c
arch/um/drivers/xterm.c
arch/um/include/chan_kern.h
arch/um/include/chan_user.h
arch/um/include/kern_util.h
arch/um/include/line.h
arch/um/include/net_kern.h
arch/um/include/os.h
arch/um/include/skas/skas.h
arch/um/include/sysdep-i386/archsetjmp.h
arch/um/include/sysdep-x86_64/archsetjmp.h
arch/um/include/sysdep-x86_64/ptrace.h
arch/um/include/sysdep-x86_64/sc.h
arch/um/kernel/Makefile
arch/um/kernel/gmon_syms.c
arch/um/kernel/ksyms.c
arch/um/kernel/mem.c
arch/um/kernel/process.c [moved from arch/um/kernel/process_kern.c with 96% similarity]
arch/um/kernel/skas/Makefile
arch/um/kernel/skas/exec.c [new file with mode: 0644]
arch/um/kernel/skas/exec_kern.c [deleted file]
arch/um/kernel/skas/process.c [new file with mode: 0644]
arch/um/kernel/skas/process_kern.c
arch/um/kernel/time.c
arch/um/kernel/trap.c
arch/um/kernel/um_arch.c
arch/um/os-Linux/Makefile
arch/um/os-Linux/drivers/etap.h
arch/um/os-Linux/drivers/ethertap_kern.c
arch/um/os-Linux/drivers/ethertap_user.c
arch/um/os-Linux/drivers/tuntap.h
arch/um/os-Linux/drivers/tuntap_kern.c
arch/um/os-Linux/drivers/tuntap_user.c
arch/um/os-Linux/skas/process.c
arch/um/sys-i386/Makefile
arch/x86_64/Kconfig
arch/x86_64/Makefile
arch/x86_64/boot/compressed/Makefile
arch/x86_64/boot/setup.S
arch/x86_64/defconfig
arch/x86_64/ia32/ia32_aout.c
arch/x86_64/ia32/ia32_signal.c
arch/x86_64/ia32/ia32entry.S
arch/x86_64/ia32/ptrace32.c
arch/x86_64/ia32/sys_ia32.c
arch/x86_64/kernel/Makefile
arch/x86_64/kernel/aperture.c
arch/x86_64/kernel/apic.c
arch/x86_64/kernel/crash.c
arch/x86_64/kernel/e820.c
arch/x86_64/kernel/early-quirks.c [new file with mode: 0644]
arch/x86_64/kernel/early_printk.c
arch/x86_64/kernel/entry.S
arch/x86_64/kernel/genapic_cluster.c
arch/x86_64/kernel/genapic_flat.c
arch/x86_64/kernel/head.S
arch/x86_64/kernel/head64.c
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/machine_kexec.c
arch/x86_64/kernel/mce.c
arch/x86_64/kernel/mce_intel.c
arch/x86_64/kernel/mpparse.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/pci-nommu.c
arch/x86_64/kernel/process.c
arch/x86_64/kernel/ptrace.c
arch/x86_64/kernel/relocate_kernel.S
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/setup64.c
arch/x86_64/kernel/signal.c
arch/x86_64/kernel/smp.c
arch/x86_64/kernel/smpboot.c
arch/x86_64/kernel/stacktrace.c
arch/x86_64/kernel/tce.c
arch/x86_64/kernel/time.c
arch/x86_64/kernel/trampoline.S
arch/x86_64/kernel/traps.c
arch/x86_64/kernel/vmlinux.lds.S
arch/x86_64/kernel/vsmp.c
arch/x86_64/kernel/vsyscall.c
arch/x86_64/kernel/x8664_ksyms.c
arch/x86_64/lib/Makefile
arch/x86_64/lib/clear_page.S
arch/x86_64/lib/copy_page.S
arch/x86_64/lib/copy_user.S
arch/x86_64/lib/csum-copy.S
arch/x86_64/lib/getuser.S
arch/x86_64/lib/iomap_copy.S
arch/x86_64/lib/memcpy.S
arch/x86_64/lib/memset.S
arch/x86_64/lib/putuser.S
arch/x86_64/lib/rwlock.S [new file with mode: 0644]
arch/x86_64/lib/thunk.S
arch/x86_64/mm/fault.c
arch/x86_64/mm/init.c
arch/x86_64/mm/k8topology.c
arch/x86_64/mm/numa.c
arch/x86_64/mm/pageattr.c
arch/x86_64/mm/srat.c
arch/x86_64/pci/Makefile
arch/x86_64/pci/mmconfig.c
block/blktrace.c
drivers/acorn/char/i2c.c
drivers/acpi/i2c_ec.c
drivers/acpi/osl.c
drivers/base/base.h
drivers/base/bus.c
drivers/base/class.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/driver.c
drivers/base/firmware_class.c
drivers/base/platform.c
drivers/base/power/resume.c
drivers/base/power/suspend.c
drivers/base/power/sysfs.c
drivers/block/loop.c
drivers/block/ub.c
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/hpet.c
drivers/char/mem.c
drivers/char/mspec.c [new file with mode: 0644]
drivers/char/watchdog/Kconfig
drivers/char/watchdog/shwdt.c
drivers/eisa/eisa-bus.c
drivers/hwmon/it87.c
drivers/hwmon/lm78.c
drivers/hwmon/pc87360.c
drivers/hwmon/sis5595.c
drivers/hwmon/smsc47b397.c
drivers/hwmon/smsc47m1.c
drivers/hwmon/via686a.c
drivers/hwmon/vt8231.c
drivers/hwmon/w83627ehf.c
drivers/hwmon/w83627hf.c
drivers/hwmon/w83781d.c
drivers/i2c/Kconfig
drivers/i2c/algos/Kconfig
drivers/i2c/algos/Makefile
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/algos/i2c-algo-pcf.c
drivers/i2c/algos/i2c-algo-sgi.c
drivers/i2c/algos/i2c-algo-sibyte.c [deleted file]
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-ali1535.c
drivers/i2c/busses/i2c-ali1563.c
drivers/i2c/busses/i2c-ali15x3.c
drivers/i2c/busses/i2c-amd756.c
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-au1550.c
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-hydra.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-i810.c
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-iop3xx.c
drivers/i2c/busses/i2c-isa.c
drivers/i2c/busses/i2c-ixp2000.c
drivers/i2c/busses/i2c-ixp4xx.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-omap.c [new file with mode: 0644]
drivers/i2c/busses/i2c-parport-light.c
drivers/i2c/busses/i2c-parport.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-powermac.c
drivers/i2c/busses/i2c-prosavage.c
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-savage4.c
drivers/i2c/busses/i2c-sibyte.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-sis630.c
drivers/i2c/busses/i2c-sis96x.c
drivers/i2c/busses/i2c-stub.c
drivers/i2c/busses/i2c-via.c
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/busses/i2c-voodoo3.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/busses/scx200_i2c.c
drivers/i2c/chips/eeprom.c
drivers/i2c/chips/isp1301_omap.c
drivers/i2c/chips/max6875.c
drivers/i2c/chips/pca9539.c
drivers/i2c/chips/pcf8574.c
drivers/i2c/chips/pcf8591.c
drivers/i2c/chips/tps65010.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/ide/ide.c
drivers/ide/ppc/pmac.c
drivers/ieee1394/pcilynx.c
drivers/infiniband/core/mad.c
drivers/infiniband/hw/ipath/ipath_fs.c
drivers/infiniband/hw/ipath/ipath_iba6110.c
drivers/infiniband/ulp/ipoib/ipoib_fs.c
drivers/input/touchscreen/hp680_ts_input.c
drivers/isdn/capi/capifs.c
drivers/isdn/gigaset/bas-gigaset.c
drivers/isdn/hisax/hfc_usb.h
drivers/media/dvb/cinergyT2/cinergyT2.c
drivers/media/dvb/dvb-usb/dvb-usb-urb.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/video/bt8xx/bttv-i2c.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-vp3054-i2c.c
drivers/media/video/ov511.c
drivers/media/video/pwc/pwc-if.c
drivers/media/video/w9968cf.c
drivers/media/video/zoran_card.c
drivers/misc/ibmasm/ibmasmfs.c
drivers/net/3c509.c
drivers/net/3c59x.c
drivers/net/acenic.c
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h
drivers/net/e1000/e1000_hw.h
drivers/net/forcedeth.c
drivers/net/gt64240eth.h [deleted file]
drivers/net/irda/irda-usb.c
drivers/net/irda/vlsi_ir.h
drivers/net/ne3210.c
drivers/net/phy/phy_device.c
drivers/net/s2io.c
drivers/net/skge.c
drivers/net/skge.h
drivers/net/smc91x.h
drivers/net/stnic.c
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/lanstreamer.h
drivers/net/tulip/de4x5.c
drivers/net/typhoon.c
drivers/net/wan/Kconfig
drivers/net/wan/Makefile
drivers/net/wan/hdlc.c [moved from drivers/net/wan/hdlc_generic.c with 67% similarity]
drivers/net/wan/hdlc_cisco.c
drivers/net/wan/hdlc_fr.c
drivers/net/wan/hdlc_ppp.c
drivers/net/wan/hdlc_raw.c
drivers/net/wan/hdlc_raw_eth.c
drivers/net/wan/hdlc_x25.c
drivers/net/wan/pc300.h
drivers/net/wan/pc300_drv.c
drivers/net/wireless/airo.c
drivers/net/wireless/atmel.c
drivers/net/wireless/bcm43xx/bcm43xx.h
drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/bcm43xx/bcm43xx_phy.c
drivers/net/wireless/bcm43xx/bcm43xx_wx.c
drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
drivers/net/wireless/hostap/hostap_ioctl.c
drivers/net/wireless/ipw2100.c
drivers/net/wireless/ipw2200.c
drivers/net/wireless/orinoco.c
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/ray_cs.c
drivers/net/wireless/wl3501_cs.c
drivers/net/wireless/zd1201.c
drivers/net/wireless/zd1211rw/zd_chip.c
drivers/net/wireless/zd1211rw/zd_chip.h
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/wireless/zd1211rw/zd_mac.h
drivers/net/wireless/zd1211rw/zd_netdev.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/net/wireless/zd1211rw/zd_usb.h
drivers/oprofile/oprofilefs.c
drivers/pci/Kconfig
drivers/pci/bus.c
drivers/pci/hotplug/acpiphp.h
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/acpiphp_ibm.c
drivers/pci/hotplug/cpqphp_sysfs.c
drivers/pci/hotplug/fakephp.c
drivers/pci/hotplug/pci_hotplug.h
drivers/pci/hotplug/pci_hotplug_core.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pcihp_skeleton.c
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_sysfs.c
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/Kconfig
drivers/pci/pcie/Makefile
drivers/pci/pcie/aer/Kconfig [new file with mode: 0644]
drivers/pci/pcie/aer/Makefile [new file with mode: 0644]
drivers/pci/pcie/aer/aerdrv.c [new file with mode: 0644]
drivers/pci/pcie/aer/aerdrv.h [new file with mode: 0644]
drivers/pci/pcie/aer/aerdrv_acpi.c [new file with mode: 0644]
drivers/pci/pcie/aer/aerdrv_core.c [new file with mode: 0644]
drivers/pci/pcie/aer/aerdrv_errprint.c [new file with mode: 0644]
drivers/pci/pcie/portdrv.h
drivers/pci/pcie/portdrv_bus.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/remove.c
drivers/pci/setup-bus.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-sh.c [new file with mode: 0644]
drivers/scsi/aha1740.c
drivers/scsi/aic7xxx/aic7770_osm.c
drivers/scsi/mesh.c
drivers/scsi/sim710.c
drivers/serial/Kconfig
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
drivers/usb/Kconfig
drivers/usb/Makefile
drivers/usb/atm/ueagle-atm.c
drivers/usb/class/usblp.c
drivers/usb/core/Makefile
drivers/usb/core/buffer.c
drivers/usb/core/config.c
drivers/usb/core/devices.c
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/endpoint.c
drivers/usb/core/file.c
drivers/usb/core/generic.c [new file with mode: 0644]
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/hcd.h
drivers/usb/core/hub.c
drivers/usb/core/hub.h
drivers/usb/core/inode.c
drivers/usb/core/message.c
drivers/usb/core/notify.c
drivers/usb/core/sysfs.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/gmidi.c [new file with mode: 0644]
drivers/usb/gadget/inode.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/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/ehci-au1xxx.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-mem.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci.h
drivers/usb/host/isp116x-hcd.c
drivers/usb/host/isp116x.h
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-au1xxx.c
drivers/usb/host/ohci-dbg.c
drivers/usb/host/ohci-ep93xx.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-lh7a404.c
drivers/usb/host/ohci-mem.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci-pnx4008.c [new file with mode: 0644]
drivers/usb/host/ohci-ppc-soc.c
drivers/usb/host/ohci-pxa27x.c
drivers/usb/host/ohci-s3c2410.c
drivers/usb/host/ohci-sa1111.c
drivers/usb/host/ohci.h
drivers/usb/host/sl811-hcd.c
drivers/usb/host/u132-hcd.c [new file with mode: 0644]
drivers/usb/host/uhci-debug.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hub.c
drivers/usb/image/mdc800.c
drivers/usb/input/Kconfig
drivers/usb/input/Makefile
drivers/usb/input/acecad.c
drivers/usb/input/appletouch.c
drivers/usb/input/ati_remote.c
drivers/usb/input/hid-core.c
drivers/usb/input/hiddev.c
drivers/usb/input/itmtouch.c
drivers/usb/input/keyspan_remote.c
drivers/usb/input/mtouchusb.c
drivers/usb/input/powermate.c
drivers/usb/input/touchkitusb.c
drivers/usb/input/trancevibrator.c [new file with mode: 0644]
drivers/usb/input/usbmouse.c
drivers/usb/input/usbtouchscreen.c
drivers/usb/input/wacom.c [deleted file]
drivers/usb/input/wacom.h [new file with mode: 0644]
drivers/usb/input/wacom_sys.c [new file with mode: 0644]
drivers/usb/input/wacom_wac.c [new file with mode: 0644]
drivers/usb/input/wacom_wac.h [new file with mode: 0644]
drivers/usb/input/yealink.c
drivers/usb/misc/Kconfig
drivers/usb/misc/Makefile
drivers/usb/misc/adutux.c [new file with mode: 0644]
drivers/usb/misc/auerswald.c
drivers/usb/misc/cypress_cy7c63.c
drivers/usb/misc/cytherm.c
drivers/usb/misc/ftdi-elan.c [new file with mode: 0644]
drivers/usb/misc/idmouse.c
drivers/usb/misc/ldusb.c
drivers/usb/misc/legousbtower.c
drivers/usb/misc/phidget.c [new file with mode: 0644]
drivers/usb/misc/phidget.h [new file with mode: 0644]
drivers/usb/misc/phidgetkit.c
drivers/usb/misc/phidgetmotorcontrol.c [new file with mode: 0644]
drivers/usb/misc/phidgetservo.c
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/usb_u132.h [new file with mode: 0644]
drivers/usb/misc/usblcd.c
drivers/usb/misc/usbled.c
drivers/usb/mon/mon_main.c
drivers/usb/mon/mon_stat.c
drivers/usb/mon/mon_text.c
drivers/usb/mon/usb_mon.h
drivers/usb/net/asix.c
drivers/usb/net/net1080.c
drivers/usb/net/pegasus.c
drivers/usb/net/rtl8150.c
drivers/usb/net/usbnet.c
drivers/usb/net/usbnet.h
drivers/usb/serial/Kconfig
drivers/usb/serial/Makefile
drivers/usb/serial/aircable.c [new file with mode: 0644]
drivers/usb/serial/airprime.c
drivers/usb/serial/ark3116.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/ipaq.c
drivers/usb/serial/mos7840.c [new file with mode: 0644]
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/usb-serial.c
drivers/usb/storage/Kconfig
drivers/usb/storage/Makefile
drivers/usb/storage/initializers.c
drivers/usb/storage/initializers.h
drivers/usb/storage/karma.c [new file with mode: 0644]
drivers/usb/storage/karma.h [new file with mode: 0644]
drivers/usb/storage/libusual.c
drivers/usb/storage/onetouch.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/transport.c
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/usb.c
drivers/usb/usb-skeleton.c
drivers/video/aty/radeon_pm.c
drivers/video/backlight/hp680_bl.c
drivers/video/console/Kconfig
drivers/video/hitfb.c
drivers/video/i810/i810-i2c.c
drivers/video/i810/i810_main.c
drivers/video/matrox/i2c-matroxfb.c
drivers/video/nvidia/nvidia.c
drivers/video/pvr2fb.c
drivers/video/savage/savagefb-i2c.c
drivers/video/savage/savagefb_driver.c
fs/9p/vfs_inode.c
fs/Kconfig
fs/adfs/inode.c
fs/adfs/super.c
fs/affs/super.c
fs/afs/inode.c
fs/afs/vlocation.c
fs/afs/volume.c
fs/autofs/inode.c
fs/autofs/symlink.c
fs/autofs4/inode.c
fs/autofs4/root.c
fs/befs/linuxvfs.c
fs/bfs/dir.c
fs/bfs/inode.c
fs/binfmt_elf.c
fs/binfmt_misc.c
fs/char_dev.c
fs/cifs/cifsfs.c
fs/cifs/readdir.c
fs/coda/coda_linux.c
fs/coda/dir.c
fs/coda/inode.c
fs/compat.c
fs/configfs/file.c
fs/configfs/inode.c
fs/cramfs/inode.c
fs/debugfs/file.c
fs/debugfs/inode.c
fs/devpts/inode.c
fs/efs/super.c
fs/eventpoll.c
fs/exec.c
fs/ext2/acl.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/ext2/super.c
fs/ext2/xattr.c
fs/ext3/acl.c
fs/ext3/balloc.c
fs/ext3/bitmap.c
fs/ext3/dir.c
fs/ext3/file.c
fs/ext3/fsync.c
fs/ext3/hash.c
fs/ext3/ialloc.c
fs/ext3/inode.c
fs/ext3/namei.c
fs/ext3/resize.c
fs/ext3/super.c
fs/ext3/xattr.c
fs/fat/cache.c
fs/fat/inode.c
fs/file.c
fs/file_table.c
fs/freevxfs/vxfs.h
fs/freevxfs/vxfs_inode.c
fs/fuse/control.c
fs/fuse/inode.c
fs/hfs/bnode.c
fs/hfs/btree.c
fs/hfs/inode.c
fs/hfs/super.c
fs/hfsplus/bnode.c
fs/hfsplus/btree.c
fs/hfsplus/inode.c
fs/hfsplus/super.c
fs/hostfs/hostfs_kern.c
fs/hpfs/buffer.c
fs/hpfs/inode.c
fs/hpfs/super.c
fs/hppfs/hppfs_kern.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/isofs/inode.c
fs/jbd/checkpoint.c
fs/jbd/journal.c
fs/jbd/recovery.c
fs/jbd/revoke.c
fs/jbd/transaction.c
fs/jffs/inode-v23.c
fs/jffs/intrep.c
fs/jffs/jffs_fm.c
fs/jffs2/fs.c
fs/jffs2/super.c
fs/jfs/jfs_extent.c
fs/jfs/jfs_imap.c
fs/jfs/jfs_inode.c
fs/jfs/jfs_metapage.c
fs/jfs/jfs_txnmgr.c
fs/libfs.c
fs/lockd/clntlock.c
fs/lockd/clntproc.c
fs/lockd/host.c
fs/lockd/svcsubs.c
fs/minix/bitmap.c
fs/minix/inode.c
fs/namei.c
fs/namespace.c
fs/ncpfs/inode.c
fs/ncpfs/symlink.c
fs/nfs/delegation.c
fs/nfs/direct.c
fs/nfs/inode.c
fs/nfs/namespace.c
fs/nfs/nfs3proc.c
fs/nfs/pagelist.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/write.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4state.c
fs/ntfs/dir.c
fs/ntfs/inode.c
fs/ntfs/mft.c
fs/ntfs/super.c
fs/ntfs/unistr.c
fs/ocfs2/dlm/dlmfs.c
fs/ocfs2/dlmglue.c
fs/ocfs2/inode.c
fs/partitions/efi.c
fs/pipe.c
fs/proc/internal.h
fs/proc/kcore.c
fs/proc/nommu.c
fs/proc/task_mmu.c
fs/proc/task_nommu.c
fs/qnx4/inode.c
fs/ramfs/inode.c
fs/reiserfs/inode.c
fs/reiserfs/super.c
fs/romfs/inode.c
fs/smbfs/inode.c
fs/smbfs/proc.c
fs/smbfs/request.c
fs/stat.c
fs/sysfs/bin.c
fs/sysfs/dir.c
fs/sysfs/inode.c
fs/sysfs/symlink.c
fs/sysfs/sysfs.h
fs/sysv/ialloc.c
fs/sysv/inode.c
fs/sysv/super.c
fs/udf/ialloc.c
fs/udf/inode.c
fs/udf/super.c
fs/ufs/ialloc.c
fs/ufs/inode.c
fs/ufs/super.c
fs/xfs/linux-2.6/kmem.h
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_vnode.c
include/asm-arm/arch-pxa/udc.h
include/asm-arm/unistd.h
include/asm-arm26/unistd.h
include/asm-frv/unistd.h
include/asm-generic/vmlinux.lds.h
include/asm-h8300/unistd.h
include/asm-i386/acpi.h
include/asm-i386/alternative-asm.i [new file with mode: 0644]
include/asm-i386/apic.h
include/asm-i386/desc.h
include/asm-i386/dwarf2.h
include/asm-i386/e820.h
include/asm-i386/frame.i [new file with mode: 0644]
include/asm-i386/genapic.h
include/asm-i386/intel_arch_perfmon.h
include/asm-i386/io_apic.h
include/asm-i386/kexec.h
include/asm-i386/mach-es7000/mach_apic.h
include/asm-i386/mach-summit/mach_apic.h
include/asm-i386/mutex.h
include/asm-i386/nmi.h
include/asm-i386/pgtable.h
include/asm-i386/ptrace.h
include/asm-i386/rwlock.h
include/asm-i386/rwsem.h
include/asm-i386/segment.h
include/asm-i386/semaphore.h
include/asm-i386/smp.h
include/asm-i386/spinlock.h
include/asm-i386/stacktrace.h [new file with mode: 0644]
include/asm-i386/therm_throt.h [new file with mode: 0644]
include/asm-i386/tlbflush.h
include/asm-i386/tsc.h
include/asm-i386/unistd.h
include/asm-i386/unwind.h
include/asm-ia64/esi.h [new file with mode: 0644]
include/asm-ia64/futex.h
include/asm-ia64/kprobes.h
include/asm-ia64/mca_asm.h
include/asm-ia64/meminit.h
include/asm-ia64/module.h
include/asm-ia64/numa.h
include/asm-ia64/pal.h
include/asm-ia64/processor.h
include/asm-ia64/smp.h
include/asm-ia64/unistd.h
include/asm-m32r/spinlock.h
include/asm-m32r/system.h
include/asm-m32r/unistd.h
include/asm-m68k/unistd.h
include/asm-m68knommu/unistd.h
include/asm-mips/Kbuild
include/asm-mips/bootinfo.h
include/asm-mips/cacheflush.h
include/asm-mips/fcntl.h
include/asm-mips/galileo-boards/gt96100.h [deleted file]
include/asm-mips/hazards.h
include/asm-mips/irq.h
include/asm-mips/mach-atlas/mc146818rtc.h
include/asm-mips/mach-ev96100/mach-gt64120.h [deleted file]
include/asm-mips/mach-excite/excite.h
include/asm-mips/mach-excite/excite_fpga.h [moved from arch/mips/basler/excite/excite_fpga.h with 100% similarity]
include/asm-mips/mach-qemu/cpu-feature-overrides.h
include/asm-mips/mips-boards/atlasint.h
include/asm-mips/mmu_context.h
include/asm-mips/page.h
include/asm-mips/pgtable-64.h
include/asm-mips/ptrace.h
include/asm-mips/serial.h
include/asm-mips/sibyte/sb1250_defs.h
include/asm-mips/sibyte/sb1250_scd.h
include/asm-mips/signal.h
include/asm-mips/spinlock.h
include/asm-mips/timex.h
include/asm-mips/unistd.h
include/asm-mips/user.h
include/asm-s390/unistd.h
include/asm-sh/addrspace.h
include/asm-sh/adx/io.h [deleted file]
include/asm-sh/apm.h [new file with mode: 0644]
include/asm-sh/atomic.h
include/asm-sh/auxvec.h
include/asm-sh/bitops.h
include/asm-sh/bugs.h
include/asm-sh/cache.h
include/asm-sh/cacheflush.h
include/asm-sh/cat68701/io.h [deleted file]
include/asm-sh/checksum.h
include/asm-sh/cpu-features.h [new file with mode: 0644]
include/asm-sh/cpu-sh2/shmparam.h [deleted file]
include/asm-sh/cpu-sh3/cache.h
include/asm-sh/cpu-sh3/cacheflush.h
include/asm-sh/cpu-sh3/freq.h
include/asm-sh/cpu-sh3/mmu_context.h
include/asm-sh/cpu-sh3/shmparam.h [deleted file]
include/asm-sh/cpu-sh3/timer.h
include/asm-sh/cpu-sh3/ubc.h
include/asm-sh/cpu-sh4/addrspace.h
include/asm-sh/cpu-sh4/cache.h
include/asm-sh/cpu-sh4/cacheflush.h
include/asm-sh/cpu-sh4/dma-sh7780.h [new file with mode: 0644]
include/asm-sh/cpu-sh4/dma.h
include/asm-sh/cpu-sh4/shmparam.h [deleted file]
include/asm-sh/cpu-sh4/sq.h
include/asm-sh/cqreek/cqreek.h [deleted file]
include/asm-sh/dma-mapping.h
include/asm-sh/dma.h
include/asm-sh/dmida/io.h [deleted file]
include/asm-sh/elf.h
include/asm-sh/fixmap.h
include/asm-sh/flat.h
include/asm-sh/harp/harp.h [deleted file]
include/asm-sh/harp/io.h [deleted file]
include/asm-sh/hd64461.h [moved from include/asm-sh/hd64461/hd64461.h with 84% similarity]
include/asm-sh/hd64461/io.h [deleted file]
include/asm-sh/hp6xx/hp6xx.h
include/asm-sh/hp6xx/io.h
include/asm-sh/hs7751rvoip/hs7751rvoip.h
include/asm-sh/io.h
include/asm-sh/irq-sh73180.h
include/asm-sh/irq-sh7343.h [new file with mode: 0644]
include/asm-sh/irq-sh7780.h
include/asm-sh/irq.h
include/asm-sh/kexec.h
include/asm-sh/kgdb.h
include/asm-sh/landisk/gio.h [new file with mode: 0644]
include/asm-sh/landisk/ide.h [new file with mode: 0644]
include/asm-sh/landisk/iodata_landisk.h [new file with mode: 0644]
include/asm-sh/machvec.h
include/asm-sh/mc146818rtc.h
include/asm-sh/mmu.h
include/asm-sh/mmu_context.h
include/asm-sh/overdrive/fpga.h [deleted file]
include/asm-sh/overdrive/gt64111.h [deleted file]
include/asm-sh/overdrive/io.h [deleted file]
include/asm-sh/overdrive/overdrive.h [deleted file]
include/asm-sh/page.h
include/asm-sh/pci.h
include/asm-sh/pgalloc.h
include/asm-sh/pgtable.h
include/asm-sh/pm.h [new file with mode: 0644]
include/asm-sh/processor.h
include/asm-sh/r7780rp/ide.h [new file with mode: 0644]
include/asm-sh/r7780rp/r7780rp.h [new file with mode: 0644]
include/asm-sh/rtc.h
include/asm-sh/rts7751r2d/rts7751r2d.h
include/asm-sh/scatterlist.h
include/asm-sh/sci.h [new file with mode: 0644]
include/asm-sh/se.h [moved from include/asm-sh/se/se.h with 97% similarity]
include/asm-sh/se/io.h [deleted file]
include/asm-sh/se7300.h [moved from include/asm-sh/se7300/se7300.h with 97% similarity]
include/asm-sh/se7300/io.h [deleted file]
include/asm-sh/se73180.h [moved from include/asm-sh/se73180/se73180.h with 97% similarity]
include/asm-sh/se73180/io.h [deleted file]
include/asm-sh/se7343.h [new file with mode: 0644]
include/asm-sh/se7751.h [moved from include/asm-sh/se7751/se7751.h with 97% similarity]
include/asm-sh/se7751/io.h [deleted file]
include/asm-sh/setup.h
include/asm-sh/sfp-machine.h [new file with mode: 0644]
include/asm-sh/sh03/io.h
include/asm-sh/sh2000/sh2000.h [deleted file]
include/asm-sh/shmin/shmin.h [new file with mode: 0644]
include/asm-sh/shmparam.h
include/asm-sh/smc37c93x.h [moved from include/asm-sh/se/smc37c93x.h with 100% similarity]
include/asm-sh/smp.h
include/asm-sh/snapgear.h [moved from include/asm-sh/snapgear/io.h with 62% similarity]
include/asm-sh/system.h
include/asm-sh/systemh/io.h [deleted file]
include/asm-sh/systemh7751.h [moved from include/asm-sh/systemh/7751systemh.h with 97% similarity]
include/asm-sh/thread_info.h
include/asm-sh/timer.h
include/asm-sh/titan.h [new file with mode: 0644]
include/asm-sh/uaccess.h
include/asm-sh/unistd.h
include/asm-sh/voyagergx.h [moved from include/asm-sh/rts7751r2d/voyagergx_reg.h with 99% similarity]
include/asm-sh/watchdog.h
include/asm-sh64/unistd.h
include/asm-um/alternative-asm.i [new file with mode: 0644]
include/asm-um/frame.i [new file with mode: 0644]
include/asm-um/processor-generic.h
include/asm-um/ptrace-x86_64.h
include/asm-v850/unistd.h
include/asm-x86_64/acpi.h
include/asm-x86_64/alternative-asm.i [new file with mode: 0644]
include/asm-x86_64/apic.h
include/asm-x86_64/bitops.h
include/asm-x86_64/calgary.h
include/asm-x86_64/dwarf2.h
include/asm-x86_64/e820.h
include/asm-x86_64/fixmap.h
include/asm-x86_64/genapic.h
include/asm-x86_64/i387.h
include/asm-x86_64/intel_arch_perfmon.h
include/asm-x86_64/io_apic.h
include/asm-x86_64/irq.h
include/asm-x86_64/kexec.h
include/asm-x86_64/linkage.h
include/asm-x86_64/mach_apic.h
include/asm-x86_64/mce.h
include/asm-x86_64/mmx.h [deleted file]
include/asm-x86_64/mpspec.h
include/asm-x86_64/msr.h
include/asm-x86_64/mutex.h
include/asm-x86_64/nmi.h
include/asm-x86_64/pci-direct.h
include/asm-x86_64/pda.h
include/asm-x86_64/percpu.h
include/asm-x86_64/pgtable.h
include/asm-x86_64/proto.h
include/asm-x86_64/rwlock.h
include/asm-x86_64/segment.h
include/asm-x86_64/semaphore.h
include/asm-x86_64/signal.h
include/asm-x86_64/smp.h
include/asm-x86_64/spinlock.h
include/asm-x86_64/stacktrace.h [new file with mode: 0644]
include/asm-x86_64/system.h
include/asm-x86_64/tce.h
include/asm-x86_64/therm_throt.h [new file with mode: 0644]
include/asm-x86_64/thread_info.h
include/asm-x86_64/tlbflush.h
include/asm-x86_64/uaccess.h
include/asm-x86_64/unistd.h
include/asm-x86_64/unwind.h
include/asm-x86_64/vsyscall.h
include/linux/aer.h [new file with mode: 0644]
include/linux/cdev.h
include/linux/compiler.h
include/linux/device.h
include/linux/edd.h
include/linux/eisa.h
include/linux/err.h
include/linux/ext3_fs.h
include/linux/ext3_fs_i.h
include/linux/ext3_jbd.h
include/linux/fs.h
include/linux/getcpu.h [new file with mode: 0644]
include/linux/gfp.h
include/linux/hdlc.h
include/linux/hdlc/ioctl.h
include/linux/i2c-algo-bit.h
include/linux/i2c-algo-pcf.h
include/linux/i2c-algo-sibyte.h [deleted file]
include/linux/i2c.h
include/linux/if.h
include/linux/init.h
include/linux/jbd.h
include/linux/jiffies.h
include/linux/kernel.h
include/linux/kobject.h
include/linux/linkage.h
include/linux/mm.h
include/linux/mm_types.h [new file with mode: 0644]
include/linux/mmzone.h
include/linux/mod_devicetable.h
include/linux/netdevice.h
include/linux/nfs_fs.h
include/linux/nfsd/nfsfh.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/pci_regs.h
include/linux/pcieport_if.h
include/linux/pid.h
include/linux/platform_device.h
include/linux/pm.h
include/linux/proc_fs.h
include/linux/sched.h
include/linux/slab.h
include/linux/smb.h
include/linux/stacktrace.h
include/linux/syscalls.h
include/linux/sysctl.h
include/linux/sysfs.h
include/linux/uaccess.h
include/linux/usb.h
include/linux/usb/audio.h [new file with mode: 0644]
include/linux/usb/midi.h [new file with mode: 0644]
include/linux/usb/otg.h [moved from include/linux/usb_otg.h with 97% similarity]
include/linux/usb_usual.h
include/linux/vermagic.h
include/linux/vmalloc.h
include/linux/wireless.h
include/media/v4l2-dev.h
init/Kconfig
init/do_mounts.c
init/main.c
ipc/mqueue.c
kernel/cpuset.c
kernel/fork.c
kernel/lockdep.c
kernel/panic.c
kernel/pid.c
kernel/power/Kconfig
kernel/power/disk.c
kernel/power/swsusp.c
kernel/power/user.c
kernel/ptrace.c
kernel/relay.c
kernel/resource.c
kernel/signal.c
kernel/spinlock.c
kernel/sys.c
kernel/sysctl.c
kernel/unwind.c
lib/Kconfig.debug
lib/hweight.c
lib/klist.c
lib/kobject.c
mm/memory.c
mm/mempolicy.c
mm/nommu.c
mm/page_alloc.c
mm/shmem.c
mm/slab.c
mm/slob.c
mm/truncate.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
net/core/net-sysfs.c
net/core/wireless.c
net/ieee80211/softmac/ieee80211softmac_wx.c
net/sunrpc/rpc_pipe.c
net/sunrpc/sched.c
scripts/Kbuild.include
scripts/gcc-x86_64-has-stack-protector.sh [new file with mode: 0644]
scripts/mod/file2alias.c
security/inode.c
security/selinux/selinuxfs.c
sound/oss/sh_dac_audio.c
sound/usb/usbmidi.c

similarity index 72%
rename from Documentation/ABI/obsolete/devfs
rename to Documentation/ABI/removed/devfs
index b8b87399bc8f22d3bb2db3ff94a77dd7df90df3f..8195c4e0d0a1002b75c55e78f43dd5855f9b3c5f 100644 (file)
@@ -1,13 +1,12 @@
 What:          devfs
-Date:          July 2005
+Date:          July 2005 (scheduled), finally removed in kernel v2.6.18
 Contact:       Greg Kroah-Hartman <gregkh@suse.de>
 Description:
        devfs has been unmaintained for a number of years, has unfixable
        races, contains a naming policy within the kernel that is
        against the LSB, and can be replaced by using udev.
-       The files fs/devfs/*, include/linux/devfs_fs*.h will be removed,
+       The files fs/devfs/*, include/linux/devfs_fs*.h were removed,
        along with the the assorted devfs function calls throughout the
        kernel tree.
 
 Users:
-
diff --git a/Documentation/ABI/testing/sysfs-power b/Documentation/ABI/testing/sysfs-power
new file mode 100644 (file)
index 0000000..d882f80
--- /dev/null
@@ -0,0 +1,88 @@
+What:          /sys/power/
+Date:          August 2006
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/power directory will contain files that will
+               provide a unified interface to the power management
+               subsystem.
+
+What:          /sys/power/state
+Date:          August 2006
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/power/state file controls the system power state.
+               Reading from this file returns what states are supported,
+               which is hard-coded to 'standby' (Power-On Suspend), 'mem'
+               (Suspend-to-RAM), and 'disk' (Suspend-to-Disk).
+
+               Writing to this file one of these strings causes the system to
+               transition into that state. Please see the file
+               Documentation/power/states.txt for a description of each of
+               these states.
+
+What:          /sys/power/disk
+Date:          August 2006
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/power/disk file controls the operating mode of the
+               suspend-to-disk mechanism.  Reading from this file returns
+               the name of the method by which the system will be put to
+               sleep on the next suspend.  There are four methods supported:
+               'firmware' - means that the memory image will be saved to disk
+               by some firmware, in which case we also assume that the
+               firmware will handle the system suspend.
+               'platform' - the memory image will be saved by the kernel and
+               the system will be put to sleep by the platform driver (e.g.
+               ACPI or other PM registers).
+               'shutdown' - the memory image will be saved by the kernel and
+               the system will be powered off.
+               'reboot' - the memory image will be saved by the kernel and
+               the system will be rebooted.
+
+               The suspend-to-disk method may be chosen by writing to this
+               file one of the accepted strings:
+
+               'firmware'
+               'platform'
+               'shutdown'
+               'reboot'
+
+               It will only change to 'firmware' or 'platform' if the system
+               supports that.
+
+What:          /sys/power/image_size
+Date:          August 2006
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/power/image_size file controls the size of the image
+               created by the suspend-to-disk mechanism.  It can be written a
+               string representing a non-negative integer that will be used
+               as an upper limit of the image size, in bytes.  The kernel's
+               suspend-to-disk code will do its best to ensure the image size
+               will not exceed this number.  However, if it turns out to be
+               impossible, the kernel will try to suspend anyway using the
+               smallest image possible.  In particular, if "0" is written to
+               this file, the suspend image will be as small as possible.
+
+               Reading from this file will display the current image size
+               limit, which is set to 500 MB by default.
+
+What:          /sys/power/pm_trace
+Date:          August 2006
+Contact:       Rafael J. Wysocki <rjw@sisk.pl>
+Description:
+               The /sys/power/pm_trace file controls the code which saves the
+               last PM event point in the RTC across reboots, so that you can
+               debug a machine that just hangs during suspend (or more
+               commonly, during resume).  Namely, the RTC is only used to save
+               the last PM event point if this file contains '1'.  Initially
+               it contains '0' which may be changed to '1' by writing a
+               string representing a nonzero integer into it.
+
+               To use this debugging feature you should attempt to suspend
+               the machine, then reboot it and run
+
+               dmesg -s 1000000 | grep 'hash matches'
+
+               CAUTION: Using it will cause your machine's real-time (CMOS)
+               clock to be set to a random invalid time after a resume.
index 320af25de3a276fd5b77aa830b08549c2c523793..3608472d7b7450ef291d07e8fb1dd4de69a9dbdf 100644 (file)
 
     <para>A Universal Serial Bus (USB) is used to connect a host,
     such as a PC or workstation, to a number of peripheral
-    devices.  USB uses a tree structure, with the host at the
+    devices.  USB uses a tree structure, with the host as the
     root (the system's master), hubs as interior nodes, and
-    peripheral devices as leaves (and slaves).
+    peripherals as leaves (and slaves).
     Modern PCs support several such trees of USB devices, usually
     one USB 2.0 tree (480 Mbit/sec each) with
     a few USB 1.1 trees (12 Mbit/sec each) that are used when you
     connect a USB 1.1 device directly to the machine's "root hub".
     </para>
 
-    <para>That master/slave asymmetry was designed in part for
-    ease of use.  It is not physically possible to assemble
-    (legal) USB cables incorrectly:  all upstream "to-the-host"
-    connectors are the rectangular typematching the sockets on
-    root hubs, and the downstream type are the squarish type
-    (or they are built in to the peripheral).
-    Software doesn't need to deal with distributed autoconfiguration
-    since the pre-designated master node manages all that.
-    At the electrical level, bus protocol overhead is reduced by
-    eliminating arbitration and moving scheduling into host software.
+    <para>That master/slave asymmetry was designed-in for a number of
+    reasons, one being ease of use.  It is not physically possible to
+    assemble (legal) USB cables incorrectly:  all upstream "to the host"
+    connectors are the rectangular type (matching the sockets on
+    root hubs), and all downstream connectors are the squarish type
+    (or they are built into the peripheral).
+    Also, the host software doesn't need to deal with distributed
+    auto-configuration since the pre-designated master node manages all that.
+    And finally, at the electrical level, bus protocol overhead is reduced by
+    eliminating arbitration and moving scheduling into the host software.
     </para>
 
-    <para>USB 1.0 was announced in January 1996, and was revised
+    <para>USB 1.0 was announced in January 1996 and was revised
     as USB 1.1 (with improvements in hub specification and
     support for interrupt-out transfers) in September 1998.
-    USB 2.0 was released in April 2000, including high speed
-    transfers and transaction translating hubs (used for USB 1.1
+    USB 2.0 was released in April 2000, adding high-speed
+    transfers and transaction-translating hubs (used for USB 1.1
     and 1.0 backward compatibility).
     </para>
 
-    <para>USB support was added to Linux early in the 2.2 kernel series
-    shortly before the 2.3 development forked off.  Updates
-    from 2.3 were regularly folded back into 2.2 releases, bringing
-    new features such as <filename>/sbin/hotplug</filename> support,
-    more drivers, and more robustness.
-    The 2.5 kernel series continued such improvements, and also
-    worked on USB 2.0 support,
-    higher performance,
-    better consistency between host controller drivers,
-    API simplification (to make bugs less likely),
-    and providing internal "kerneldoc" documentation.
+    <para>Kernel developers added USB support to Linux early in the 2.2 kernel
+    series, shortly before 2.3 development forked.  Updates from 2.3 were
+    regularly folded back into 2.2 releases, which improved reliability and
+    brought <filename>/sbin/hotplug</filename> support as well more drivers.
+    Such improvements were continued in the 2.5 kernel series, where they added
+    USB 2.0 support, improved performance, and made the host controller drivers
+    (HCDs) more consistent.  They also simplified the API (to make bugs less
+    likely) and added internal "kerneldoc" documentation.
     </para>
 
     <para>Linux can run inside USB devices as well as on
     the hosts that control the devices.
-    Because the Linux 2.x USB support evolved to support mass market
-    platforms such as Apple Macintosh or PC-compatible systems,
-    it didn't address design concerns for those types of USB systems.
-    So it can't be used inside mass-market PDAs, or other peripherals.
-    USB device drivers running inside those Linux peripherals
+    But USB device drivers running inside those peripherals
     don't do the same things as the ones running inside hosts,
-    and so they've been given a different name:
-    they're called <emphasis>gadget drivers</emphasis>.
-    This document does not present gadget drivers.
+    so they've been given a different name:
+    <emphasis>gadget drivers</emphasis>.
+    This document does not cover gadget drivers.
     </para>
 
     </chapter>
 <chapter id="host">
     <title>USB Host-Side API Model</title>
 
-    <para>Within the kernel,
-    host-side drivers for USB devices talk to the "usbcore" APIs.
-    There are two types of public "usbcore" APIs, targetted at two different
-    layers of USB driver.  Those are
-    <emphasis>general purpose</emphasis> drivers, exposed through
-    driver frameworks such as block, character, or network devices;
-    and drivers that are <emphasis>part of the core</emphasis>,
-    which are involved in managing a USB bus.
-    Such core drivers include the <emphasis>hub</emphasis> driver,
-    which manages trees of USB devices, and several different kinds
-    of <emphasis>host controller driver (HCD)</emphasis>,
+    <para>Host-side drivers for USB devices talk to the "usbcore" APIs.
+    There are two.  One is intended for
+    <emphasis>general-purpose</emphasis> drivers (exposed through
+    driver frameworks), and the other is for drivers that are
+    <emphasis>part of the core</emphasis>.
+    Such core drivers include the <emphasis>hub</emphasis> driver
+    (which manages trees of USB devices) and several different kinds
+    of <emphasis>host controller drivers</emphasis>,
     which control individual busses.
     </para>
 
      
     <itemizedlist>
 
-       <listitem><para>USB supports four kinds of data transfer
-       (control, bulk, interrupt, and isochronous).  Two transfer
-       types use bandwidth as it's available (control and bulk),
-       while the other two types of transfer (interrupt and isochronous)
+       <listitem><para>USB supports four kinds of data transfers
+       (control, bulk, interrupt, and isochronous).  Two of them (control
+       and bulk) use bandwidth as it's available,
+       while the other two (interrupt and isochronous)
        are scheduled to provide guaranteed bandwidth.
        </para></listitem>
 
        <listitem><para>The device description model includes one or more
        "configurations" per device, only one of which is active at a time.
-       Devices that are capable of high speed operation must also support
-       full speed configurations, along with a way to ask about the
-       "other speed" configurations that might be used.
+       Devices that are capable of high-speed operation must also support
+       full-speed configurations, along with a way to ask about the
+       "other speed" configurations which might be used.
        </para></listitem>
 
-       <listitem><para>Configurations have one or more "interface", each
+       <listitem><para>Configurations have one or more "interfaces", each
        of which may have "alternate settings".  Interfaces may be
        standardized by USB "Class" specifications, or may be specific to
        a vendor or device.</para>
        </para></listitem>
 
        <listitem><para>The Linux USB API supports synchronous calls for
-       control and bulk messaging.
+       control and bulk messages.
        It also supports asynchnous calls for all kinds of data transfer,
        using request structures called "URBs" (USB Request Blocks).
        </para></listitem>
            file in your Linux kernel sources.
            </para>
 
-           <para>Otherwise the main use for this file from programs
-           is to poll() it to get notifications of usb devices
-           as they're plugged or unplugged.
-           To see what changed, you'd need to read the file and
-           compare "before" and "after" contents, scan the filesystem,
-           or see its hotplug event.
+           <para>This file, in combination with the poll() system call, can
+           also be used to detect when devices are added or removed:
+<programlisting>int fd;
+struct pollfd pfd;
+
+fd = open("/proc/bus/usb/devices", O_RDONLY);
+pfd = { fd, POLLIN, 0 };
+for (;;) {
+       /* The first time through, this call will return immediately. */
+       poll(&amp;pfd, 1, -1);
+
+       /* To see what's changed, compare the file's previous and current
+          contents or scan the filesystem.  (Scanning is more precise.) */
+}</programlisting>
+           Note that this behavior is intended to be used for informational
+           and debug purposes.  It would be more appropriate to use programs
+           such as udev or HAL to initialize a device or start a user-mode
+           helper program, for instance.
            </para>
-
        </sect1>
 
        <sect1>
index 915ae8c986c68a9ac3041cd072c6f7697353ee02..1d6560413cc593e001080759ce867c070956aeb7 100644 (file)
@@ -358,7 +358,8 @@ Here is a list of some of the different kernel trees available:
   quilt trees:
     - USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de>
        kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
-
+    - x86-64, partly i386, Andi Kleen <ak@suse.de>
+        ftp.firstfloor.org:/pub/ak/x86_64/quilt/
 
 Bug Reporting
 -------------
index 66c725f530f38b2c836f52ced2fa898c640f8db1..addc67b1d770e26fd0dee02613866a40735f01b1 100644 (file)
@@ -2543,6 +2543,9 @@ Your cooperation is appreciated.
                 64 = /dev/usb/rio500   Diamond Rio 500
                 65 = /dev/usb/usblcd   USBLCD Interface (info@usblcd.de)
                 66 = /dev/usb/cpad0    Synaptics cPad (mouse/LCD)
+                67 = /dev/usb/adutux0  1st Ontrak ADU device
+                   ...
+                76 = /dev/usb/adutux10 10th Ontrak ADU device
                 96 = /dev/usb/hiddev0  1st USB HID device
                    ...
                111 = /dev/usb/hiddev15 16th USB HID device
index 552507fe9a7ead2498dd4d696b53498da4be40e9..436697cb93882e174199d7f00efc1d243954ac75 100644 (file)
@@ -6,6 +6,21 @@ be removed from this file.
 
 ---------------------------
 
+What:  /sys/devices/.../power/state
+       dev->power.power_state
+       dpm_runtime_{suspend,resume)()
+When:  July 2007
+Why:   Broken design for runtime control over driver power states, confusing
+       driver-internal runtime power management with:  mechanisms to support
+       system-wide sleep state transitions; event codes that distinguish
+       different phases of swsusp "sleep" transitions; and userspace policy
+       inputs.  This framework was never widely used, and most attempts to
+       use it were broken.  Drivers should instead be exposing domain-specific
+       interfaces either to kernel or to userspace.
+Who:   Pavel Machek <pavel@suse.cz>
+
+---------------------------
+
 What:  RAW driver (CONFIG_RAW_DRIVER)
 When:  December 2005
 Why:   declared obsolete since kernel 2.6.3
@@ -55,6 +70,18 @@ Who: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
 
 ---------------------------
 
+What:  sys_sysctl
+When:  January 2007
+Why:   The same information is available through /proc/sys and that is the
+       interface user space prefers to use. And there do not appear to be
+       any existing user in user space of sys_sysctl.  The additional
+       maintenance overhead of keeping a set of binary names gets
+       in the way of doing a good job of maintaining this interface.
+
+Who:   Eric Biederman <ebiederm@xmission.com>
+
+---------------------------
+
 What:  PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
 When:  November 2005
 Files: drivers/pcmcia/: pcmcia_ioctl.c
@@ -202,14 +229,6 @@ Who:       Nick Piggin <npiggin@suse.de>
 
 ---------------------------
 
-What:  Support for the MIPS EV96100 evaluation board
-When:  September 2006
-Why:   Does no longer build since at least November 15, 2003, apparently
-       no userbase left.
-Who:   Ralf Baechle <ralf@linux-mips.org>
-
----------------------------
-
 What:  Support for the Momentum / PMC-Sierra Jaguar ATX evaluation board
 When:  September 2006
 Why:   Does no longer build since quite some time, and was never popular,
@@ -294,3 +313,24 @@ Why:       The frame diverter is included in most distribution kernels, but is
        It is not clear if anyone is still using it.
 Who:   Stephen Hemminger <shemminger@osdl.org>
 
+---------------------------
+
+
+What:  PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment
+When:  Oktober 2008
+Why:   The stacking of class devices makes these values misleading and
+       inconsistent.
+       Class devices should not carry any of these properties, and bus
+       devices have SUBSYTEM and DRIVER as a replacement.
+Who:   Kay Sievers <kay.sievers@suse.de>
+
+---------------------------
+
+What:  i2c-isa
+When:  December 2006
+Why:   i2c-isa is a non-sense and doesn't fit in the device driver
+       model. Drivers relying on it are better implemented as platform
+       drivers.
+Who:   Jean Delvare <khali@linux-fr.org>
+
+---------------------------
index 99902ae6804e6edb0550fac53ce34b9070842895..7db71d6fba824bc92f08785578d7dc8fefb4c5aa 100644 (file)
@@ -1124,11 +1124,15 @@ debugging information is displayed on console.
 NMI switch that most IA32 servers have fires unknown NMI up, for example.
 If a system hangs up, try pressing the NMI switch.
 
-[NOTE]
-   This function and oprofile share a NMI callback. Therefore this function
-   cannot be enabled when oprofile is activated.
-   And NMI watchdog will be disabled when the value in this file is set to
-   non-zero.
+nmi_watchdog
+------------
+
+Enables/Disables the NMI watchdog on x86 systems.  When the value is non-zero
+the NMI watchdog is enabled and will continuously test all online cpus to
+determine whether or not they are still functioning properly.
+
+Because the NMI watchdog shares registers with oprofile, by disabling the NMI
+watchdog, oprofile may have more registers to utilize.
 
 
 2.4 /proc/sys/vm - The virtual memory subsystem
index 16775663b9f5a5f9831fa2e251299352cced3ec7..25680346e0acd2059bf23608f5982b8bb2163eaf 100644 (file)
@@ -7,9 +7,12 @@ Supported adapters:
   * VIA Technologies, Inc. VT82C686A/B
     Datasheet: Sometimes available at the VIA website
 
-  * VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237R
+  * VIA Technologies, Inc. VT8231, VT8233, VT8233A
     Datasheet: available on request from VIA
 
+  * VIA Technologies, Inc. VT8235, VT8237R, VT8237A, VT8251
+    Datasheet: available on request and under NDA from VIA
+
 Authors:
        Kyösti Mälkki <kmalkki@cc.hut.fi>,
        Mark D. Studebaker <mdsxyz123@yahoo.com>,
@@ -39,6 +42,8 @@ Your lspci -n listing must show one of these :
  device 1106:8235   (VT8231 function 4)
  device 1106:3177   (VT8235)
  device 1106:3227   (VT8237R)
+ device 1106:3337   (VT8237A)
+ device 1106:3287   (VT8251)
 
 If none of these show up, you should look in the BIOS for settings like
 enable ACPI / SMBus or even USB.
index d6dcb138abf510534d2539665f74176c013a37b4..9cc081e697648ecb3feaadddcc4b8da187294db9 100644 (file)
@@ -6,9 +6,12 @@ This module is a very simple fake I2C/SMBus driver.  It implements four
 types of SMBus commands: write quick, (r/w) byte, (r/w) byte data, and
 (r/w) word data.
 
+You need to provide a chip address as a module parameter when loading
+this driver, which will then only react to SMBus commands to this address.
+
 No hardware is needed nor associated with this module.  It will accept write
-quick commands to all addresses; it will respond to the other commands (also
-to all addresses) by reading from or writing to an array in memory.  It will
+quick commands to one address; it will respond to the other commands (also
+to one address) by reading from or writing to an array in memory.  It will
 also spam the kernel logs for every command it handles.
 
 A pointer register with auto-increment is implemented for all byte
@@ -21,6 +24,11 @@ The typical use-case is like this:
        3. load the target sensors chip driver module
        4. observe its behavior in the kernel log
 
+PARAMETERS:
+
+int chip_addr:
+       The SMBus address to emulate a chip at.
+
 CAVEATS:
 
 There are independent arrays for byte/data and word/data commands.  Depending
@@ -33,6 +41,9 @@ If the hardware for your driver has banked registers (e.g. Winbond sensors
 chips) this module will not work well - although it could be extended to
 support that pretty easily.
 
+Only one chip address is supported - although this module could be
+extended to support more.
+
 If you spam it hard enough, printk can be lossy.  This module really wants
 something like relayfs.
 
index b7d6abb501a6458ce8e30176b2a5205a3240398a..e2cbd59cf2d0bdcf82ba99064dbf50b86b976f38 100644 (file)
@@ -421,6 +421,11 @@ more details, with real examples.
        The second argument is optional, and if supplied will be used
        if first argument is not supported.
 
+    as-instr
+       as-instr checks if the assembler reports a specific instruction
+       and then outputs either option1 or option2
+       C escapes are supported in the test instruction
+
     cc-option
        cc-option is used to check if $(CC) supports a given option, and not
        supported to use an optional second option.
index 766abdab94e70b939233f2fdc62be70275a9f3de..54983246930d1aeb922c3691ac0b5a96028d97ef 100644 (file)
@@ -573,8 +573,6 @@ running once the system is up.
        gscd=           [HW,CD]
                        Format: <io>
 
-       gt96100eth=     [NET] MIPS GT96100 Advanced Communication Controller
-
        gus=            [HW,OSS]
                        Format: <io>,<irq>,<dma>,<dma16>
 
@@ -1240,7 +1238,11 @@ running once the system is up.
                                bootloader. This is currently used on
                                IXP2000 systems where the bus has to be
                                configured a certain way for adjunct CPUs.
-
+               noearly         [X86] Don't do any early type 1 scanning.
+                               This might help on some broken boards which
+                               machine check when some devices' config space
+                               is read. But various workarounds are disabled
+                               and some IOMMU drivers will not work.
        pcmv=           [HW,PCMCIA] BadgePAD 4
 
        pd.             [PARIDE]
@@ -1368,6 +1370,9 @@ running once the system is up.
                        Reserves a hole at the top of the kernel virtual
                        address space.
 
+       reset_devices   [KNL] Force drivers to reset the underlying device
+                       during initialization.
+
        resume=         [SWSUSP]
                        Specify the partition device for software suspend
 
index afac780445cd19a9042a629fa32245d11806e610..dc942eaf490fb8474a136f10a132d375d7759635 100644 (file)
@@ -192,6 +192,17 @@ or, for backwards compatibility, the option value.  E.g.,
 arp_interval
 
        Specifies the ARP link monitoring frequency in milliseconds.
+
+       The ARP monitor works by periodically checking the slave
+       devices to determine whether they have sent or received
+       traffic recently (the precise criteria depends upon the
+       bonding mode, and the state of the slave).  Regular traffic is
+       generated via ARP probes issued for the addresses specified by
+       the arp_ip_target option.
+
+       This behavior can be modified by the arp_validate option,
+       below.
+
        If ARP monitoring is used in an etherchannel compatible mode
        (modes 0 and 2), the switch should be configured in a mode
        that evenly distributes packets across all links. If the
@@ -213,6 +224,54 @@ arp_ip_target
        maximum number of targets that can be specified is 16.  The
        default value is no IP addresses.
 
+arp_validate
+
+       Specifies whether or not ARP probes and replies should be
+       validated in the active-backup mode.  This causes the ARP
+       monitor to examine the incoming ARP requests and replies, and
+       only consider a slave to be up if it is receiving the
+       appropriate ARP traffic.
+
+       Possible values are:
+
+       none or 0
+
+               No validation is performed.  This is the default.
+
+       active or 1
+
+               Validation is performed only for the active slave.
+
+       backup or 2
+
+               Validation is performed only for backup slaves.
+
+       all or 3
+
+               Validation is performed for all slaves.
+
+       For the active slave, the validation checks ARP replies to
+       confirm that they were generated by an arp_ip_target.  Since
+       backup slaves do not typically receive these replies, the
+       validation performed for backup slaves is on the ARP request
+       sent out via the active slave.  It is possible that some
+       switch or network configurations may result in situations
+       wherein the backup slaves do not receive the ARP requests; in
+       such a situation, validation of backup slaves must be
+       disabled.
+
+       This option is useful in network configurations in which
+       multiple bonding hosts are concurrently issuing ARPs to one or
+       more targets beyond a common switch.  Should the link between
+       the switch and target fail (but not the switch itself), the
+       probe traffic generated by the multiple bonding instances will
+       fool the standard ARP monitor into considering the links as
+       still up.  Use of the arp_validate option can resolve this, as
+       the ARP monitor will only consider ARP requests and replies
+       associated with its own instance of bonding.
+
+       This option was added in bonding version 3.1.0.
+
 downdelay
 
        Specifies the time, in milliseconds, to wait before disabling
index b88ebe4d808c36a9bc6526354562a121bd245ea2..7714f57caad5b4312e7289761c0561c68b822049 100644 (file)
@@ -116,6 +116,9 @@ FURTHER NOTES ON NO-MMU MMAP
  (*) A list of all the mappings on the system is visible through /proc/maps in
      no-MMU mode.
 
+ (*) A list of all the mappings in use by a process is visible through
+     /proc/<pid>/maps in no-MMU mode.
+
  (*) Supplying MAP_FIXED or a requesting a particular mapping address will
      result in an error.
 
@@ -125,6 +128,49 @@ FURTHER NOTES ON NO-MMU MMAP
      error will result if they don't. This is most likely to be encountered
      with character device files, pipes, fifos and sockets.
 
+
+==========================
+INTERPROCESS SHARED MEMORY
+==========================
+
+Both SYSV IPC SHM shared memory and POSIX shared memory is supported in NOMMU
+mode.  The former through the usual mechanism, the latter through files created
+on ramfs or tmpfs mounts.
+
+
+=======
+FUTEXES
+=======
+
+Futexes are supported in NOMMU mode if the arch supports them.  An error will
+be given if an address passed to the futex system call lies outside the
+mappings made by a process or if the mapping in which the address lies does not
+support futexes (such as an I/O chardev mapping).
+
+
+=============
+NO-MMU MREMAP
+=============
+
+The mremap() function is partially supported.  It may change the size of a
+mapping, and may move it[*] if MREMAP_MAYMOVE is specified and if the new size
+of the mapping exceeds the size of the slab object currently occupied by the
+memory to which the mapping refers, or if a smaller slab object could be used.
+
+MREMAP_FIXED is not supported, though it is ignored if there's no change of
+address and the object does not need to be moved.
+
+Shared mappings may not be moved.  Shareable mappings may not be moved either,
+even if they are not currently shared.
+
+The mremap() function must be given an exact match for base address and size of
+a previously mapped object.  It may not be used to create holes in existing
+mappings, move parts of existing mappings or resize parts of mappings.  It must
+act on a complete mapping.
+
+[*] Not currently supported.
+
+
 ============================================
 PROVIDING SHAREABLE CHARACTER DEVICE SUPPORT
 ============================================
diff --git a/Documentation/pcieaer-howto.txt b/Documentation/pcieaer-howto.txt
new file mode 100644 (file)
index 0000000..16c2512
--- /dev/null
@@ -0,0 +1,253 @@
+   The PCI Express Advanced Error Reporting Driver Guide HOWTO
+               T. Long Nguyen  <tom.l.nguyen@intel.com>
+               Yanmin Zhang    <yanmin.zhang@intel.com>
+                               07/29/2006
+
+
+1. Overview
+
+1.1 About this guide
+
+This guide describes the basics of the PCI Express Advanced Error
+Reporting (AER) driver and provides information on how to use it, as
+well as how to enable the drivers of endpoint devices to conform with
+PCI Express AER driver.
+
+1.2 Copyright Â© Intel Corporation 2006.
+
+1.3 What is the PCI Express AER Driver?
+
+PCI Express error signaling can occur on the PCI Express link itself
+or on behalf of transactions initiated on the link. PCI Express
+defines two error reporting paradigms: the baseline capability and
+the Advanced Error Reporting capability. The baseline capability is
+required of all PCI Express components providing a minimum defined
+set of error reporting requirements. Advanced Error Reporting
+capability is implemented with a PCI Express advanced error reporting
+extended capability structure providing more robust error reporting.
+
+The PCI Express AER driver provides the infrastructure to support PCI
+Express Advanced Error Reporting capability. The PCI Express AER
+driver provides three basic functions:
+
+-      Gathers the comprehensive error information if errors occurred.
+-      Reports error to the users.
+-      Performs error recovery actions.
+
+AER driver only attaches root ports which support PCI-Express AER
+capability.
+
+
+2. User Guide
+
+2.1 Include the PCI Express AER Root Driver into the Linux Kernel
+
+The PCI Express AER Root driver is a Root Port service driver attached
+to the PCI Express Port Bus driver. If a user wants to use it, the driver
+has to be compiled. Option CONFIG_PCIEAER supports this capability. It
+depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and
+CONFIG_PCIEAER = y.
+
+2.2 Load PCI Express AER Root Driver
+There is a case where a system has AER support in BIOS. Enabling the AER
+Root driver and having AER support in BIOS may result unpredictable
+behavior. To avoid this conflict, a successful load of the AER Root driver
+requires ACPI _OSC support in the BIOS to allow the AER Root driver to
+request for native control of AER. See the PCI FW 3.0 Specification for
+details regarding OSC usage. Currently, lots of firmwares don't provide
+_OSC support while they use PCI Express. To support such firmwares,
+forceload, a parameter of type bool, could enable AER to continue to
+be initiated although firmwares have no _OSC support. To enable the
+walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
+when booting kernel. Note that forceload=n by default.
+
+2.3 AER error output
+When a PCI-E AER error is captured, an error message will be outputed to
+console. If it's a correctable error, it is outputed as a warning.
+Otherwise, it is printed as an error. So users could choose different
+log level to filter out correctable error messages.
+
+Below shows an example.
++------ PCI-Express Device Error -----+
+Error Severity          : Uncorrected (Fatal)
+PCIE Bus Error type     : Transaction Layer
+Unsupported Request     : First
+Requester ID            : 0500
+VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h
+TLB Header:
+04000001 00200a03 05010000 00050100
+
+In the example, 'Requester ID' means the ID of the device who sends
+the error message to root port. Pls. refer to pci express specs for
+other fields.
+
+
+3. Developer Guide
+
+To enable AER aware support requires a software driver to configure
+the AER capability structure within its device and to provide callbacks.
+
+To support AER better, developers need understand how AER does work
+firstly.
+
+PCI Express errors are classified into two types: correctable errors
+and uncorrectable errors. This classification is based on the impacts
+of those errors, which may result in degraded performance or function
+failure.
+
+Correctable errors pose no impacts on the functionality of the
+interface. The PCI Express protocol can recover without any software
+intervention or any loss of data. These errors are detected and
+corrected by hardware. Unlike correctable errors, uncorrectable
+errors impact functionality of the interface. Uncorrectable errors
+can cause a particular transaction or a particular PCI Express link
+to be unreliable. Depending on those error conditions, uncorrectable
+errors are further classified into non-fatal errors and fatal errors.
+Non-fatal errors cause the particular transaction to be unreliable,
+but the PCI Express link itself is fully functional. Fatal errors, on
+the other hand, cause the link to be unreliable.
+
+When AER is enabled, a PCI Express device will automatically send an
+error message to the PCIE root port above it when the device captures
+an error. The Root Port, upon receiving an error reporting message,
+internally processes and logs the error message in its PCI Express
+capability structure. Error information being logged includes storing
+the error reporting agent's requestor ID into the Error Source
+Identification Registers and setting the error bits of the Root Error
+Status Register accordingly. If AER error reporting is enabled in Root
+Error Command Register, the Root Port generates an interrupt if an
+error is detected.
+
+Note that the errors as described above are related to the PCI Express
+hierarchy and links. These errors do not include any device specific
+errors because device specific errors will still get sent directly to
+the device driver.
+
+3.1 Configure the AER capability structure
+
+AER aware drivers of PCI Express component need change the device
+control registers to enable AER. They also could change AER registers,
+including mask and severity registers. Helper function
+pci_enable_pcie_error_reporting could be used to enable AER. See
+section 3.3.
+
+3.2. Provide callbacks
+
+3.2.1 callback reset_link to reset pci express link
+
+This callback is used to reset the pci express physical link when a
+fatal error happens. The root port aer service driver provides a
+default reset_link function, but different upstream ports might
+have different specifications to reset pci express link, so all
+upstream ports should provide their own reset_link functions.
+
+In struct pcie_port_service_driver, a new pointer, reset_link, is
+added.
+
+pci_ers_result_t (*reset_link) (struct pci_dev *dev);
+
+Section 3.2.2.2 provides more detailed info on when to call
+reset_link.
+
+3.2.2 PCI error-recovery callbacks
+
+The PCI Express AER Root driver uses error callbacks to coordinate
+with downstream device drivers associated with a hierarchy in question
+when performing error recovery actions.
+
+Data struct pci_driver has a pointer, err_handler, to point to
+pci_error_handlers who consists of a couple of callback function
+pointers. AER driver follows the rules defined in
+pci-error-recovery.txt except pci express specific parts (e.g.
+reset_link). Pls. refer to pci-error-recovery.txt for detailed
+definitions of the callbacks.
+
+Below sections specify when to call the error callback functions.
+
+3.2.2.1 Correctable errors
+
+Correctable errors pose no impacts on the functionality of
+the interface. The PCI Express protocol can recover without any
+software intervention or any loss of data. These errors do not
+require any recovery actions. The AER driver clears the device's
+correctable error status register accordingly and logs these errors.
+
+3.2.2.2 Non-correctable (non-fatal and fatal) errors
+
+If an error message indicates a non-fatal error, performing link reset
+at upstream is not required. The AER driver calls error_detected(dev,
+pci_channel_io_normal) to all drivers associated within a hierarchy in
+question. for example,
+EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort.
+If Upstream port A captures an AER error, the hierarchy consists of
+Downstream port B and EndPoint.
+
+A driver may return PCI_ERS_RESULT_CAN_RECOVER,
+PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on
+whether it can recover or the AER driver calls mmio_enabled as next.
+
+If an error message indicates a fatal error, kernel will broadcast
+error_detected(dev, pci_channel_io_frozen) to all drivers within
+a hierarchy in question. Then, performing link reset at upstream is
+necessary. As different kinds of devices might use different approaches
+to reset link, AER port service driver is required to provide the
+function to reset link. Firstly, kernel looks for if the upstream
+component has an aer driver. If it has, kernel uses the reset_link
+callback of the aer driver. If the upstream component has no aer driver
+and the port is downstream port, we will use the aer driver of the
+root port who reports the AER error. As for upstream ports,
+they should provide their own aer service drivers with reset_link
+function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
+reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
+to mmio_enabled.
+
+3.3 helper functions
+
+3.3.1 int pci_find_aer_capability(struct pci_dev *dev);
+pci_find_aer_capability locates the PCI Express AER capability
+in the device configuration space. If the device doesn't support
+PCI-Express AER, the function returns 0.
+
+3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev);
+pci_enable_pcie_error_reporting enables the device to send error
+messages to root port when an error is detected. Note that devices
+don't enable the error reporting by default, so device drivers need
+call this function to enable it.
+
+3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev);
+pci_disable_pcie_error_reporting disables the device to send error
+messages to root port when an error is detected.
+
+3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable
+error status register.
+
+3.4 Frequent Asked Questions
+
+Q: What happens if a PCI Express device driver does not provide an
+error recovery handler (pci_driver->err_handler is equal to NULL)?
+
+A: The devices attached with the driver won't be recovered. If the
+error is fatal, kernel will print out warning messages. Please refer
+to section 3 for more information.
+
+Q: What happens if an upstream port service driver does not provide
+callback reset_link?
+
+A: Fatal error recovery will fail if the errors are reported by the
+upstream ports who are attached by the service driver.
+
+Q: How does this infrastructure deal with driver that is not PCI
+Express aware?
+
+A: This infrastructure calls the error callback functions of the
+driver when an error happens. But if the driver is not aware of
+PCI Express, the device might not report its own errors to root
+port.
+
+Q: What modifications will that driver need to make it compatible
+with the PCI Express AER Root driver?
+
+A: It could call the helper functions to enable AER in devices and
+cleanup uncorrectable status register. Pls. refer to section 3.3.
+
index fba1e05c47c72e558e162c2153d5feee62a4c97f..d0e79d5820a5e7a7237f36a1cb5776ec589552d8 100644 (file)
+Most of the code in Linux is device drivers, so most of the Linux power
+management code is also driver-specific.  Most drivers will do very little;
+others, especially for platforms with small batteries (like cell phones),
+will do a lot.
+
+This writeup gives an overview of how drivers interact with system-wide
+power management goals, emphasizing the models and interfaces that are
+shared by everything that hooks up to the driver model core.  Read it as
+background for the domain-specific work you'd do with any specific driver.
+
+
+Two Models for Device Power Management
+======================================
+Drivers will use one or both of these models to put devices into low-power
+states:
+
+    System Sleep model:
+       Drivers can enter low power states as part of entering system-wide
+       low-power states like "suspend-to-ram", or (mostly for systems with
+       disks) "hibernate" (suspend-to-disk).
+
+       This is something that device, bus, and class drivers collaborate on
+       by implementing various role-specific suspend and resume methods to
+       cleanly power down hardware and software subsystems, then reactivate
+       them without loss of data.
+
+       Some drivers can manage hardware wakeup events, which make the system
+       leave that low-power state.  This feature may be disabled using the
+       relevant /sys/devices/.../power/wakeup file; enabling it may cost some
+       power usage, but let the whole system enter low power states more often.
+
+    Runtime Power Management model:
+       Drivers may also enter low power states while the system is running,
+       independently of other power management activity.  Upstream drivers
+       will normally not know (or care) if the device is in some low power
+       state when issuing requests; the driver will auto-resume anything
+       that's needed when it gets a request.
+
+       This doesn't have, or need much infrastructure; it's just something you
+       should do when writing your drivers.  For example, clk_disable() unused
+       clocks as part of minimizing power drain for currently-unused hardware.
+       Of course, sometimes clusters of drivers will collaborate with each
+       other, which could involve task-specific power management.
+
+There's not a lot to be said about those low power states except that they
+are very system-specific, and often device-specific.  Also, that if enough
+drivers put themselves into low power states (at "runtime"), the effect may be
+the same as entering some system-wide low-power state (system sleep) ... and
+that synergies exist, so that several drivers using runtime pm might put the
+system into a state where even deeper power saving options are available.
+
+Most suspended devices will have quiesced all I/O:  no more DMA or irqs, no
+more data read or written, and requests from upstream drivers are no longer
+accepted.  A given bus or platform may have different requirements though.
+
+Examples of hardware wakeup events include an alarm from a real time clock,
+network wake-on-LAN packets, keyboard or mouse activity, and media insertion
+or removal (for PCMCIA, MMC/SD, USB, and so on).
+
+
+Interfaces for Entering System Sleep States
+===========================================
+Most of the programming interfaces a device driver needs to know about
+relate to that first model:  entering a system-wide low power state,
+rather than just minimizing power consumption by one device.
+
+
+Bus Driver Methods
+------------------
+The core methods to suspend and resume devices reside in struct bus_type.
+These are mostly of interest to people writing infrastructure for busses
+like PCI or USB, or because they define the primitives that device drivers
+may need to apply in domain-specific ways to their devices:
 
-Device Power Management
+struct bus_type {
+       ...
+       int  (*suspend)(struct device *dev, pm_message_t state);
+       int  (*suspend_late)(struct device *dev, pm_message_t state);
 
+       int  (*resume_early)(struct device *dev);
+       int  (*resume)(struct device *dev);
+};
 
-Device power management encompasses two areas - the ability to save
-state and transition a device to a low-power state when the system is
-entering a low-power state; and the ability to transition a device to
-a low-power state while the system is running (and independently of
-any other power management activity). 
+Bus drivers implement those methods as appropriate for the hardware and
+the drivers using it; PCI works differently from USB, and so on.  Not many
+people write bus drivers; most driver code is a "device driver" that
+builds on top of bus-specific framework code.
+
+For more information on these driver calls, see the description later;
+they are called in phases for every device, respecting the parent-child
+sequencing in the driver model tree.  Note that as this is being written,
+only the suspend() and resume() are widely available; not many bus drivers
+leverage all of those phases, or pass them down to lower driver levels.
+
+
+/sys/devices/.../power/wakeup files
+-----------------------------------
+All devices in the driver model have two flags to control handling of
+wakeup events, which are hardware signals that can force the device and/or
+system out of a low power state.  These are initialized by bus or device
+driver code using device_init_wakeup(dev,can_wakeup).
+
+The "can_wakeup" flag just records whether the device (and its driver) can
+physically support wakeup events.  When that flag is clear, the sysfs
+"wakeup" file is empty, and device_may_wakeup() returns false.
+
+For devices that can issue wakeup events, a separate flag controls whether
+that device should try to use its wakeup mechanism.  The initial value of
+device_may_wakeup() will be true, so that the device's "wakeup" file holds
+the value "enabled".  Userspace can change that to "disabled" so that
+device_may_wakeup() returns false; or change it back to "enabled" (so that
+it returns true again).
+
+
+EXAMPLE:  PCI Device Driver Methods
+-----------------------------------
+PCI framework software calls these methods when the PCI device driver bound
+to a device device has provided them:
+
+struct pci_driver {
+       ...
+       int  (*suspend)(struct pci_device *pdev, pm_message_t state);
+       int  (*suspend_late)(struct pci_device *pdev, pm_message_t state);
+
+       int  (*resume_early)(struct pci_device *pdev);
+       int  (*resume)(struct pci_device *pdev);
+};
 
+Drivers will implement those methods, and call PCI-specific procedures
+like pci_set_power_state(), pci_enable_wake(), pci_save_state(), and
+pci_restore_state() to manage PCI-specific mechanisms.  (PCI config space
+could be saved during driver probe, if it weren't for the fact that some
+systems rely on userspace tweaking using setpci.)  Devices are suspended
+before their bridges enter low power states, and likewise bridges resume
+before their devices.
+
+
+Upper Layers of Driver Stacks
+-----------------------------
+Device drivers generally have at least two interfaces, and the methods
+sketched above are the ones which apply to the lower level (nearer PCI, USB,
+or other bus hardware).  The network and block layers are examples of upper
+level interfaces, as is a character device talking to userspace.
+
+Power management requests normally need to flow through those upper levels,
+which often use domain-oriented requests like "blank that screen".  In
+some cases those upper levels will have power management intelligence that
+relates to end-user activity, or other devices that work in cooperation.
+
+When those interfaces are structured using class interfaces, there is a
+standard way to have the upper layer stop issuing requests to a given
+class device (and restart later):
+
+struct class {
+       ...
+       int  (*suspend)(struct device *dev, pm_message_t state);
+       int  (*resume)(struct device *dev);
+};
 
-Methods
+Those calls are issued in specific phases of the process by which the
+system enters a low power "suspend" state, or resumes from it.
+
+
+Calling Drivers to Enter System Sleep States
+============================================
+When the system enters a low power state, each device's driver is asked
+to suspend the device by putting it into state compatible with the target
+system state.  That's usually some version of "off", but the details are
+system-specific.  Also, wakeup-enabled devices will usually stay partly
+functional in order to wake the system.
+
+When the system leaves that low power state, the device's driver is asked
+to resume it.  The suspend and resume operations always go together, and
+both are multi-phase operations.
+
+For simple drivers, suspend might quiesce the device using the class code
+and then turn its hardware as "off" as possible with late_suspend.  The
+matching resume calls would then completely reinitialize the hardware
+before reactivating its class I/O queues.
+
+More power-aware drivers drivers will use more than one device low power
+state, either at runtime or during system sleep states, and might trigger
+system wakeup events.
+
+
+Call Sequence Guarantees
+------------------------
+To ensure that bridges and similar links needed to talk to a device are
+available when the device is suspended or resumed, the device tree is
+walked in a bottom-up order to suspend devices.  A top-down order is
+used to resume those devices.
+
+The ordering of the device tree is defined by the order in which devices
+get registered:  a child can never be registered, probed or resumed before
+its parent; and can't be removed or suspended after that parent.
+
+The policy is that the device tree should match hardware bus topology.
+(Or at least the control bus, for devices which use multiple busses.)
+
+
+Suspending Devices
+------------------
+Suspending a given device is done in several phases.  Suspending the
+system always includes every phase, executing calls for every device
+before the next phase begins.  Not all busses or classes support all
+these callbacks; and not all drivers use all the callbacks.
+
+The phases are seen by driver notifications issued in this order:
+
+   1   class.suspend(dev, message) is called after tasks are frozen, for
+       devices associated with a class that has such a method.  This
+       method may sleep.
+
+       Since I/O activity usually comes from such higher layers, this is
+       a good place to quiesce all drivers of a given type (and keep such
+       code out of those drivers).
+
+   2   bus.suspend(dev, message) is called next.  This method may sleep,
+       and is often morphed into a device driver call with bus-specific
+       parameters and/or rules.
+
+       This call should handle parts of device suspend logic that require
+       sleeping.  It probably does work to quiesce the device which hasn't
+       been abstracted into class.suspend() or bus.suspend_late().
+
+   3   bus.suspend_late(dev, message) is called with IRQs disabled, and
+       with only one CPU active.  Until the bus.resume_early() phase
+       completes (see later), IRQs are not enabled again.  This method
+       won't be exposed by all busses; for message based busses like USB,
+       I2C, or SPI, device interactions normally require IRQs.  This bus
+       call may be morphed into a driver call with bus-specific parameters.
+
+       This call might save low level hardware state that might otherwise
+       be lost in the upcoming low power state, and actually put the
+       device into a low power state ... so that in some cases the device
+       may stay partly usable until this late.  This "late" call may also
+       help when coping with hardware that behaves badly.
+
+The pm_message_t parameter is currently used to refine those semantics
+(described later).
+
+At the end of those phases, drivers should normally have stopped all I/O
+transactions (DMA, IRQs), saved enough state that they can re-initialize
+or restore previous state (as needed by the hardware), and placed the
+device into a low-power state.  On many platforms they will also use
+clk_disable() to gate off one or more clock sources; sometimes they will
+also switch off power supplies, or reduce voltages.  Drivers which have
+runtime PM support may already have performed some or all of the steps
+needed to prepare for the upcoming system sleep state.
+
+When any driver sees that its device_can_wakeup(dev), it should make sure
+to use the relevant hardware signals to trigger a system wakeup event.
+For example, enable_irq_wake() might identify GPIO signals hooked up to
+a switch or other external hardware, and pci_enable_wake() does something
+similar for PCI's PME# signal.
+
+If a driver (or bus, or class) fails it suspend method, the system won't
+enter the desired low power state; it will resume all the devices it's
+suspended so far.
+
+Note that drivers may need to perform different actions based on the target
+system lowpower/sleep state.  At this writing, there are only platform
+specific APIs through which drivers could determine those target states.
+
+
+Device Low Power (suspend) States
+---------------------------------
+Device low-power states aren't very standard.  One device might only handle
+"on" and "off, while another might support a dozen different versions of
+"on" (how many engines are active?), plus a state that gets back to "on"
+faster than from a full "off".
+
+Some busses define rules about what different suspend states mean.  PCI
+gives one example:  after the suspend sequence completes, a non-legacy
+PCI device may not perform DMA or issue IRQs, and any wakeup events it
+issues would be issued through the PME# bus signal.  Plus, there are
+several PCI-standard device states, some of which are optional.
+
+In contrast, integrated system-on-chip processors often use irqs as the
+wakeup event sources (so drivers would call enable_irq_wake) and might
+be able to treat DMA completion as a wakeup event (sometimes DMA can stay
+active too, it'd only be the CPU and some peripherals that sleep).
+
+Some details here may be platform-specific.  Systems may have devices that
+can be fully active in certain sleep states, such as an LCD display that's
+refreshed using DMA while most of the system is sleeping lightly ... and
+its frame buffer might even be updated by a DSP or other non-Linux CPU while
+the Linux control processor stays idle.
+
+Moreover, the specific actions taken may depend on the target system state.
+One target system state might allow a given device to be very operational;
+another might require a hard shut down with re-initialization on resume.
+And two different target systems might use the same device in different
+ways; the aforementioned LCD might be active in one product's "standby",
+but a different product using the same SOC might work differently.
+
+
+Meaning of pm_message_t.event
+-----------------------------
+Parameters to suspend calls include the device affected and a message of
+type pm_message_t, which has one field:  the event.  If driver does not
+recognize the event code, suspend calls may abort the request and return
+a negative errno.  However, most drivers will be fine if they implement
+PM_EVENT_SUSPEND semantics for all messages.
+
+The event codes are used to refine the goal of suspending the device, and
+mostly matter when creating or resuming system memory image snapshots, as
+used with suspend-to-disk:
+
+    PM_EVENT_SUSPEND -- quiesce the driver and put hardware into a low-power
+       state.  When used with system sleep states like "suspend-to-RAM" or
+       "standby", the upcoming resume() call will often be able to rely on
+       state kept in hardware, or issue system wakeup events.  When used
+       instead with suspend-to-disk, few devices support this capability;
+       most are completely powered off.
+
+    PM_EVENT_FREEZE -- quiesce the driver, but don't necessarily change into
+       any low power mode.  A system snapshot is about to be taken, often
+       followed by a call to the driver's resume() method.  Neither wakeup
+       events nor DMA are allowed.
+
+    PM_EVENT_PRETHAW -- quiesce the driver, knowing that the upcoming resume()
+       will restore a suspend-to-disk snapshot from a different kernel image.
+       Drivers that are smart enough to look at their hardware state during
+       resume() processing need that state to be correct ... a PRETHAW could
+       be used to invalidate that state (by resetting the device), like a
+       shutdown() invocation would before a kexec() or system halt.  Other
+       drivers might handle this the same way as PM_EVENT_FREEZE.  Neither
+       wakeup events nor DMA are allowed.
+
+To enter "standby" (ACPI S1) or "Suspend to RAM" (STR, ACPI S3) states, or
+the similarly named APM states, only PM_EVENT_SUSPEND is used; for "Suspend
+to Disk" (STD, hibernate, ACPI S4), all of those event codes are used.
+
+There's also PM_EVENT_ON, a value which never appears as a suspend event
+but is sometimes used to record the "not suspended" device state.
+
+
+Resuming Devices
+----------------
+Resuming is done in multiple phases, much like suspending, with all
+devices processing each phase's calls before the next phase begins.
+
+The phases are seen by driver notifications issued in this order:
+
+   1   bus.resume_early(dev) is called with IRQs disabled, and with
+       only one CPU active.  As with bus.suspend_late(), this method
+       won't be supported on busses that require IRQs in order to
+       interact with devices.
+
+       This reverses the effects of bus.suspend_late().
+
+   2   bus.resume(dev) is called next.  This may be morphed into a device
+       driver call with bus-specific parameters; implementations may sleep.
+
+       This reverses the effects of bus.suspend().
+
+   3   class.resume(dev) is called for devices associated with a class
+       that has such a method.  Implementations may sleep.
+
+       This reverses the effects of class.suspend(), and would usually
+       reactivate the device's I/O queue.
+
+At the end of those phases, drivers should normally be as functional as
+they were before suspending:  I/O can be performed using DMA and IRQs, and
+the relevant clocks are gated on.  The device need not be "fully on"; it
+might be in a runtime lowpower/suspend state that acts as if it were.
+
+However, the details here may again be platform-specific.  For example,
+some systems support multiple "run" states, and the mode in effect at
+the end of resume() might not be the one which preceded suspension.
+That means availability of certain clocks or power supplies changed,
+which could easily affect how a driver works.
+
+
+Drivers need to be able to handle hardware which has been reset since the
+suspend methods were called, for example by complete reinitialization.
+This may be the hardest part, and the one most protected by NDA'd documents
+and chip errata.  It's simplest if the hardware state hasn't changed since
+the suspend() was called, but that can't always be guaranteed.
+
+Drivers must also be prepared to notice that the device has been removed
+while the system was powered off, whenever that's physically possible.
+PCMCIA, MMC, USB, Firewire, SCSI, and even IDE are common examples of busses
+where common Linux platforms will see such removal.  Details of how drivers
+will notice and handle such removals are currently bus-specific, and often
+involve a separate thread.
 
-The methods to suspend and resume devices reside in struct bus_type: 
 
-struct bus_type {
-       ...
-       int             (*suspend)(struct device * dev, pm_message_t state);
-       int             (*resume)(struct device * dev);
-};
+Note that the bus-specific runtime PM wakeup mechanism can exist, and might
+be defined to share some of the same driver code as for system wakeup.  For
+example, a bus-specific device driver's resume() method might be used there,
+so it wouldn't only be called from bus.resume() during system-wide wakeup.
+See bus-specific information about how runtime wakeup events are handled.
 
-Each bus driver is responsible implementing these methods, translating
-the call into a bus-specific request and forwarding the call to the
-bus-specific drivers. For example, PCI drivers implement suspend() and
-resume() methods in struct pci_driver. The PCI core is simply
-responsible for translating the pointers to PCI-specific ones and
-calling the low-level driver.
-
-This is done to a) ease transition to the new power management methods
-and leverage the existing PM code in various bus drivers; b) allow
-buses to implement generic and default PM routines for devices, and c)
-make the flow of execution obvious to the reader. 
-
-
-System Power Management
-
-When the system enters a low-power state, the device tree is walked in
-a depth-first fashion to transition each device into a low-power
-state. The ordering of the device tree is guaranteed by the order in
-which devices get registered - children are never registered before
-their ancestors, and devices are placed at the back of the list when
-registered. By walking the list in reverse order, we are guaranteed to
-suspend devices in the proper order. 
-
-Devices are suspended once with interrupts enabled. Drivers are
-expected to stop I/O transactions, save device state, and place the
-device into a low-power state. Drivers may sleep, allocate memory,
-etc. at will. 
-
-Some devices are broken and will inevitably have problems powering
-down or disabling themselves with interrupts enabled. For these
-special cases, they may return -EAGAIN. This will put the device on a
-list to be taken care of later. When interrupts are disabled, before
-we enter the low-power state, their drivers are called again to put
-their device to sleep. 
-
-On resume, the devices that returned -EAGAIN will be called to power
-themselves back on with interrupts disabled. Once interrupts have been
-re-enabled, the rest of the drivers will be called to resume their
-devices. On resume, a driver is responsible for powering back on each
-device, restoring state, and re-enabling I/O transactions for that
-device. 
 
+System Devices
+--------------
 System devices follow a slightly different API, which can be found in
 
        include/linux/sysdev.h
        drivers/base/sys.c
 
-System devices will only be suspended with interrupts disabled, and
-after all other devices have been suspended. On resume, they will be
-resumed before any other devices, and also with interrupts disabled.
+System devices will only be suspended with interrupts disabled, and after
+all other devices have been suspended.  On resume, they will be resumed
+before any other devices, and also with interrupts disabled.
 
+That is, IRQs are disabled, the suspend_late() phase begins, then the
+sysdev_driver.suspend() phase, and the system enters a sleep state.  Then
+the sysdev_driver.resume() phase begins, followed by the resume_early()
+phase, after which IRQs are enabled.
 
-Runtime Power Management
-
-Many devices are able to dynamically power down while the system is
-still running. This feature is useful for devices that are not being
-used, and can offer significant power savings on a running system. 
-
-In each device's directory, there is a 'power' directory, which
-contains at least a 'state' file. Reading from this file displays what
-power state the device is currently in. Writing to this file initiates
-a transition to the specified power state, which must be a decimal in
-the range 1-3, inclusive; or 0 for 'On'.
+Code to actually enter and exit the system-wide low power state sometimes
+involves hardware details that are only known to the boot firmware, and
+may leave a CPU running software (from SRAM or flash memory) that monitors
+the system and manages its wakeup sequence.
 
-The PM core will call the ->suspend() method in the bus_type object
-that the device belongs to if the specified state is not 0, or
-->resume() if it is. 
 
-Nothing will happen if the specified state is the same state the
-device is currently in. 
-
-If the device is already in a low-power state, and the specified state
-is another, but different, low-power state, the ->resume() method will
-first be called to power the device back on, then ->suspend() will be
-called again with the new state. 
-
-The driver is responsible for saving the working state of the device
-and putting it into the low-power state specified. If this was
-successful, it returns 0, and the device's power_state field is
-updated. 
-
-The driver must take care to know whether or not it is able to
-properly resume the device, including all step of reinitialization
-necessary. (This is the hardest part, and the one most protected by
-NDA'd documents). 
-
-The driver must also take care not to suspend a device that is
-currently in use. It is their responsibility to provide their own
-exclusion mechanisms.
-
-The runtime power transition happens with interrupts enabled. If a
-device cannot support being powered down with interrupts, it may
-return -EAGAIN (as it would during a system power management
-transition),  but it will _not_ be called again, and the transaction
-will fail.
-
-There is currently no way to know what states a device or driver
-supports a priori. This will change in the future. 
-
-pm_message_t meaning
-
-pm_message_t has two fields. event ("major"), and flags.  If driver
-does not know event code, it aborts the request, returning error. Some
-drivers may need to deal with special cases based on the actual type
-of suspend operation being done at the system level. This is why
-there are flags.
-
-Event codes are:
-
-ON -- no need to do anything except special cases like broken
-HW.
-
-# NOTIFICATION -- pretty much same as ON?
-
-FREEZE -- stop DMA and interrupts, and be prepared to reinit HW from
-scratch. That probably means stop accepting upstream requests, the
-actual policy of what to do with them being specific to a given
-driver. It's acceptable for a network driver to just drop packets
-while a block driver is expected to block the queue so no request is
-lost. (Use IDE as an example on how to do that). FREEZE requires no
-power state change, and it's expected for drivers to be able to
-quickly transition back to operating state.
-
-SUSPEND -- like FREEZE, but also put hardware into low-power state. If
-there's need to distinguish several levels of sleep, additional flag
-is probably best way to do that.
-
-Transitions are only from a resumed state to a suspended state, never
-between 2 suspended states. (ON -> FREEZE or ON -> SUSPEND can happen,
-FREEZE -> SUSPEND or SUSPEND -> FREEZE can not).
-
-All events are:
-
-[NOTE NOTE NOTE: If you are driver author, you should not care; you
-should only look at event, and ignore flags.]
-
-#Prepare for suspend -- userland is still running but we are going to
-#enter suspend state. This gives drivers chance to load firmware from
-#disk and store it in memory, or do other activities taht require
-#operating userland, ability to kmalloc GFP_KERNEL, etc... All of these
-#are forbiden once the suspend dance is started.. event = ON, flags =
-#PREPARE_TO_SUSPEND
-
-Apm standby -- prepare for APM event. Quiesce devices to make life
-easier for APM BIOS. event = FREEZE, flags = APM_STANDBY
-
-Apm suspend -- same as APM_STANDBY, but it we should probably avoid
-spinning down disks. event = FREEZE, flags = APM_SUSPEND
-
-System halt, reboot -- quiesce devices to make life easier for BIOS. event
-= FREEZE, flags = SYSTEM_HALT or SYSTEM_REBOOT
-
-System shutdown -- at least disks need to be spun down, or data may be
-lost. Quiesce devices, just to make life easier for BIOS. event =
-FREEZE, flags = SYSTEM_SHUTDOWN
-
-Kexec    -- turn off DMAs and put hardware into some state where new
-kernel can take over. event = FREEZE, flags = KEXEC
-
-Powerdown at end of swsusp -- very similar to SYSTEM_SHUTDOWN, except wake
-may need to be enabled on some devices. This actually has at least 3
-subtypes, system can reboot, enter S4 and enter S5 at the end of
-swsusp. event = FREEZE, flags = SWSUSP and one of SYSTEM_REBOOT,
-SYSTEM_SHUTDOWN, SYSTEM_S4
-
-Suspend to ram  -- put devices into low power state. event = SUSPEND,
-flags = SUSPEND_TO_RAM
-
-Freeze for swsusp snapshot -- stop DMA and interrupts. No need to put
-devices into low power mode, but you must be able to reinitialize
-device from scratch in resume method. This has two flavors, its done
-once on suspending kernel, once on resuming kernel. event = FREEZE,
-flags = DURING_SUSPEND or DURING_RESUME
-
-Device detach requested from /sys -- deinitialize device; proably same as
-SYSTEM_SHUTDOWN, I do not understand this one too much. probably event
-= FREEZE, flags = DEV_DETACH.
-
-#These are not really events sent:
-#
-#System fully on -- device is working normally; this is probably never
-#passed to suspend() method... event = ON, flags = 0
-#
-#Ready after resume -- userland is now running, again. Time to free any
-#memory you ate during prepare to suspend... event = ON, flags =
-#READY_AFTER_RESUME
-#
+Runtime Power Management
+========================
+Many devices are able to dynamically power down while the system is still
+running. This feature is useful for devices that are not being used, and
+can offer significant power savings on a running system.  These devices
+often support a range of runtime power states, which might use names such
+as "off", "sleep", "idle", "active", and so on.  Those states will in some
+cases (like PCI) be partially constrained by a bus the device uses, and will
+usually include hardware states that are also used in system sleep states.
+
+However, note that if a driver puts a device into a runtime low power state
+and the system then goes into a system-wide sleep state, it normally ought
+to resume into that runtime low power state rather than "full on".  Such
+distinctions would be part of the driver-internal state machine for that
+hardware; the whole point of runtime power management is to be sure that
+drivers are decoupled in that way from the state machine governing phases
+of the system-wide power/sleep state transitions.
+
+
+Power Saving Techniques
+-----------------------
+Normally runtime power management is handled by the drivers without specific
+userspace or kernel intervention, by device-aware use of techniques like:
+
+    Using information provided by other system layers
+       - stay deeply "off" except between open() and close()
+       - if transceiver/PHY indicates "nobody connected", stay "off"
+       - application protocols may include power commands or hints
+
+    Using fewer CPU cycles
+       - using DMA instead of PIO
+       - removing timers, or making them lower frequency
+       - shortening "hot" code paths
+       - eliminating cache misses
+       - (sometimes) offloading work to device firmware
+
+    Reducing other resource costs
+       - gating off unused clocks in software (or hardware)
+       - switching off unused power supplies
+       - eliminating (or delaying/merging) IRQs
+       - tuning DMA to use word and/or burst modes
+
+    Using device-specific low power states
+       - using lower voltages
+       - avoiding needless DMA transfers
+
+Read your hardware documentation carefully to see the opportunities that
+may be available.  If you can, measure the actual power usage and check
+it against the budget established for your project.
+
+
+Examples:  USB hosts, system timer, system CPU
+----------------------------------------------
+USB host controllers make interesting, if complex, examples.  In many cases
+these have no work to do:  no USB devices are connected, or all of them are
+in the USB "suspend" state.  Linux host controller drivers can then disable
+periodic DMA transfers that would otherwise be a constant power drain on the
+memory subsystem, and enter a suspend state.  In power-aware controllers,
+entering that suspend state may disable the clock used with USB signaling,
+saving a certain amount of power.
+
+The controller will be woken from that state (with an IRQ) by changes to the
+signal state on the data lines of a given port, for example by an existing
+peripheral requesting "remote wakeup" or by plugging a new peripheral.  The
+same wakeup mechanism usually works from "standby" sleep states, and on some
+systems also from "suspend to RAM" (or even "suspend to disk") states.
+(Except that ACPI may be involved instead of normal IRQs, on some hardware.)
+
+System devices like timers and CPUs may have special roles in the platform
+power management scheme.  For example, system timers using a "dynamic tick"
+approach don't just save CPU cycles (by eliminating needless timer IRQs),
+but they may also open the door to using lower power CPU "idle" states that
+cost more than a jiffie to enter and exit.  On x86 systems these are states
+like "C3"; note that periodic DMA transfers from a USB host controller will
+also prevent entry to a C3 state, much like a periodic timer IRQ.
+
+That kind of runtime mechanism interaction is common.  "System On Chip" (SOC)
+processors often have low power idle modes that can't be entered unless
+certain medium-speed clocks (often 12 or 48 MHz) are gated off.  When the
+drivers gate those clocks effectively, then the system idle task may be able
+to use the lower power idle modes and thereby increase battery life.
+
+If the CPU can have a "cpufreq" driver, there also may be opportunities
+to shift to lower voltage settings and reduce the power cost of executing
+a given number of instructions.  (Without voltage adjustment, it's rare
+for cpufreq to save much power; the cost-per-instruction must go down.)
+
+
+/sys/devices/.../power/state files
+==================================
+For now you can also test some of this functionality using sysfs.
+
+       DEPRECATED:  USE "power/state" ONLY FOR DRIVER TESTING, AND
+       AVOID USING dev->power.power_state IN DRIVERS.
+
+       THESE WILL BE REMOVED.  IF THE "power/state" FILE GETS REPLACED,
+       IT WILL BECOME SOMETHING COUPLED TO THE BUS OR DRIVER.
+
+In each device's directory, there is a 'power' directory, which contains
+at least a 'state' file.  The value of this field is effectively boolean,
+PM_EVENT_ON or PM_EVENT_SUSPEND.
+
+   *   Reading from this file displays a value corresponding to
+       the power.power_state.event field.  All nonzero values are
+       displayed as "2", corresponding to a low power state; zero
+       is displayed as "0", corresponding to normal operation.
+
+   *   Writing to this file initiates a transition using the
+       specified event code number; only '0', '2', and '3' are
+       accepted (without a newline); '2' and '3' are both
+       mapped to PM_EVENT_SUSPEND.
+
+On writes, the PM core relies on that recorded event code and the device/bus
+capabilities to determine whether it uses a partial suspend() or resume()
+sequence to change things so that the recorded event corresponds to the
+numeric parameter.
+
+   -   If the bus requires the irqs-disabled suspend_late()/resume_early()
+       phases, writes fail because those operations are not supported here.
+
+   -   If the recorded value is the expected value, nothing is done.
+
+   -   If the recorded value is nonzero, the device is partially resumed,
+       using the bus.resume() and/or class.resume() methods.
+
+   -   If the target value is nonzero, the device is partially suspended,
+       using the class.suspend() and/or bus.suspend() methods and the
+       PM_EVENT_SUSPEND message.
+
+Drivers have no way to tell whether their suspend() and resume() calls
+have come through the sysfs power/state file or as part of entering a
+system sleep state, except that when accessed through sysfs the normal
+parent/child sequencing rules are ignored.  Drivers (such as bus, bridge,
+or hub drivers) which expose child devices may need to enforce those rules
+on their own.
index eb2dd2e6993bebeffa684ba51ebd2e4957fa6b8a..73988e0d112b490ad187144e88a7904b2ab49000 100644 (file)
@@ -41,11 +41,6 @@ Board-specific code:
         |
        .. more boards here ...
 
-It should also be noted that each board is required to have some certain
-headers. At the time of this writing, io.h is the only thing that needs
-to be provided for each board, and can generally just reference generic
-functions (with the exception of isa_port2addr).
-
 Next, for companion chips:
 .
 `-- arch
@@ -104,12 +99,13 @@ and then populate that with sub-directories for each member of the family.
 Both the Solution Engine and the hp6xx boards are an example of this.
 
 After you have setup your new arch/sh/boards/ directory, remember that you
-also must add a directory in include/asm-sh for headers localized to this
-board. In order to interoperate seamlessly with the build system, it's best
-to have this directory the same as the arch/sh/boards/ directory name,
-though if your board is again part of a family, the build system has ways
-of dealing with this, and you can feel free to name the directory after
-the family member itself.
+should also add a directory in include/asm-sh for headers localized to this
+board (if there are going to be more than one). In order to interoperate
+seamlessly with the build system, it's best to have this directory the same
+as the arch/sh/boards/ directory name, though if your board is again part of
+a family, the build system has ways of dealing with this (via incdir-y
+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
@@ -122,6 +118,7 @@ might look something like:
  * arch/sh/boards/vapor/setup.c - Setup code for imaginary board
  */
 #include <linux/init.h>
+#include <asm/rtc.h> /* for board_time_init() */
 
 const char *get_system_type(void)
 {
@@ -152,79 +149,57 @@ int __init platform_setup(void)
 }
 
 Our new imaginary board will also have to tie into the machvec in order for it
-to be of any use. Currently the machvec is slowly on its way out, but is still
-required for the time being. As such, let us take a look at what needs to be
-done for the machvec assignment.
+to be of any use.
 
 machvec functions fall into a number of categories:
 
  - I/O functions to IO memory (inb etc) and PCI/main memory (readb etc).
- - I/O remapping functions (ioremap etc)
- - some initialisation functions
- - a 'heartbeat' function
- - some miscellaneous flags
-
-The tree can be built in two ways:
- - as a fully generic build. All drivers are linked in, and all functions
-   go through the machvec
- - as a machine specific build. In this case only the required drivers
-   will be linked in, and some macros may be redefined to not go through
-   the machvec where performance is important (in particular IO functions).
-
-There are three ways in which IO can be performed:
- - none at all. This is really only useful for the 'unknown' machine type,
-   which us designed to run on a machine about which we know nothing, and
-   so all all IO instructions do nothing.
- - fully custom. In this case all IO functions go to a machine specific
-   set of functions which can do what they like
- - a generic set of functions. These will cope with most situations,
-   and rely on a single function, mv_port2addr, which is called through the
-   machine vector, and converts an IO address into a memory address, which
-   can be read from/written to directly.
-
-Thus adding a new machine involves the following steps (I will assume I am
-adding a machine called vapor):
-
- - add a new file include/asm-sh/vapor/io.h which contains prototypes for
+ - I/O mapping functions (ioport_map, ioport_unmap, etc).
+ - a 'heartbeat' function.
+ - PCI and IRQ initialization routines.
+ - Consistent allocators (for boards that need special allocators,
+   particularly for allocating out of some board-specific SRAM for DMA
+   handles).
+
+There are machvec functions added and removed over time, so always be sure to
+consult include/asm-sh/machvec.h for the current state of the machvec.
+
+The kernel will automatically wrap in generic routines for undefined function
+pointers in the machvec at boot time, as machvec functions are referenced
+unconditionally throughout most of the tree. Some boards have incredibly
+sparse machvecs (such as the dreamcast and sh03), whereas others must define
+virtually everything (rts7751r2d).
+
+Adding a new machine is relatively trivial (using vapor as an example):
+
+If the board-specific definitions are quite minimalistic, as is the case for
+the vast majority of boards, simply having a single board-specific header is
+sufficient.
+
+ - add a new file include/asm-sh/vapor.h which contains prototypes for
    any machine specific IO functions prefixed with the machine name, for
    example vapor_inb. These will be needed when filling out the machine
    vector.
 
-   This is the minimum that is required, however there are ample
-   opportunities to optimise this. In particular, by making the prototypes
-   inline function definitions, it is possible to inline the function when
-   building machine specific versions. Note that the machine vector
-   functions will still be needed, so that a module built for a generic
-   setup can be loaded.
-
- - add a new file arch/sh/boards/vapor/mach.c. This contains the definition
-   of the machine vector. When building the machine specific version, this
-   will be the real machine vector (via an alias), while in the generic
-   version is used to initialise the machine vector, and then freed, by
-   making it initdata. This should be defined as:
-
-     struct sh_machine_vector mv_vapor __initmv = {
-       .mv_name = "vapor",
-     }
-     ALIAS_MV(vapor)
-
- - finally add a file arch/sh/boards/vapor/io.c, which contains
-   definitions of the machine specific io functions.
-
-A note about initialisation functions. Three initialisation functions are
-provided in the machine vector:
- - mv_arch_init - called very early on from setup_arch
- - mv_init_irq - called from init_IRQ, after the generic SH interrupt
-   initialisation
- - mv_init_pci - currently not used
-
-Any other remaining functions which need to be called at start up can be
-added to the list using the __initcalls macro (or module_init if the code
-can be built as a module). Many generic drivers probe to see if the device
-they are targeting is present, however this may not always be appropriate,
-so a flag can be added to the machine vector which will be set on those
-machines which have the hardware in question, reducing the probe to a
-single conditional.
+   Note that these prototypes are generated automatically by setting
+   __IO_PREFIX to something sensible. A typical example would be:
+
+       #define __IO_PREFIX vapor
+       #include <asm/io_generic.h>
+
+   somewhere in the board-specific header. Any boards being ported that still
+   have a legacy io.h should remove it entirely and switch to the new model.
+
+ - Add machine vector definitions to the board's setup.c. At a bare minimum,
+   this must be defined as something like:
+
+       struct sh_machine_vector mv_vapor __initmv = {
+               .mv_name = "vapor",
+       };
+       ALIAS_MV(vapor)
+
+ - finally add a file arch/sh/boards/vapor/io.c, which contains definitions of
+   the machine specific io functions (if there are enough to warrant it).
 
 3. Hooking into the Build System
 ================================
@@ -303,4 +278,3 @@ which will in turn copy the defconfig for this board, run it through
 oldconfig (prompting you for any new options since the time of creation),
 and start you on your way to having a functional kernel for your new
 board.
-
diff --git a/Documentation/sh/register-banks.txt b/Documentation/sh/register-banks.txt
new file mode 100644 (file)
index 0000000..a6719f2
--- /dev/null
@@ -0,0 +1,33 @@
+       Notes on register bank usage in the kernel
+       ==========================================
+
+Introduction
+------------
+
+The SH-3 and SH-4 CPU families traditionally include a single partial register
+bank (selected by SR.RB, only r0 ... r7 are banked), whereas other families
+may have more full-featured banking or simply no such capabilities at all.
+
+SR.RB banking
+-------------
+
+In the case of this type of banking, banked registers are mapped directly to
+r0 ... r7 if SR.RB is set to the bank we are interested in, otherwise ldc/stc
+can still be used to reference the banked registers (as r0_bank ... r7_bank)
+when in the context of another bank. The developer must keep the SR.RB value
+in mind when writing code that utilizes these banked registers, for obvious
+reasons. Userspace is also not able to poke at the bank1 values, so these can
+be used rather effectively as scratch registers by the kernel.
+
+Presently the kernel uses several of these registers.
+
+       - r0_bank, r1_bank (referenced as k0 and k1, used for scratch
+         registers when doing exception handling).
+       - r2_bank (used to track the EXPEVT/INTEVT code)
+               - Used by do_IRQ() and friends for doing irq mapping based off
+                 of the interrupt exception vector jump table offset
+       - r6_bank (global interrupt mask)
+               - The SR.IMASK interrupt handler makes use of this to set the
+                 interrupt priority level (used by local_irq_enable())
+       - r7_bank (current)
+
index 867f4c38f3564ae8fcfa8aa92df2b8eb41cfa31a..39c68f8c4e6c7cd8969fa1f0ae03a1afd1bcc424 100644 (file)
@@ -98,13 +98,13 @@ one or more packets could finish before an error stops further endpoint I/O.
                        error, a failure to respond (often caused by
                        device disconnect), or some other fault.
 
--ETIMEDOUT (**)                No response packet received within the prescribed
+-ETIME (**)            No response packet received within the prescribed
                        bus turn-around time.  This error may instead be
                        reported as -EPROTO or -EILSEQ.
 
-                       Note that the synchronous USB message functions
-                       also use this code to indicate timeout expired
-                       before the transfer completed.
+-ETIMEDOUT             Synchronous USB message functions use this code
+                       to indicate timeout expired before the transfer
+                       completed, and no other error was reported by HC.
 
 -EPIPE (**)            Endpoint stalled.  For non-control endpoints,
                        reset this status with usb_clear_halt().
@@ -163,6 +163,3 @@ usb_get_*/usb_set_*():
 usb_control_msg():
 usb_bulk_msg():
 -ETIMEDOUT             Timeout expired before the transfer completed.
-                       In the future this code may change to -ETIME,
-                       whose definition is a closer match to this sort
-                       of error.
index 02b0f7beb6d1623e542d7610e91971eeca2ce614..a2dee6e6190d73e9c1c266cf3544a5e252e8b5eb 100644 (file)
@@ -433,6 +433,11 @@ Options supported:
   See http://www.uuhaus.de/linux/palmconnect.html for up-to-date
   information on this driver.
 
+AIRcable USB Dongle Bluetooth driver
+  If there is the cdc_acm driver loaded in the system, you will find that the
+  cdc_acm claims the device before AIRcable can. This is simply corrected
+  by unloading both modules and then loading the aircable module before
+  cdc_acm module
 
 Generic Serial driver
 
index 6da24e7a56cba01c9b7af0a0e1c894667a614d75..4303e0c12476d1afb4af9c7998e46cb2ed4b7494 100644 (file)
@@ -245,6 +245,13 @@ 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
 
   noreplacement  Don't replace instructions with more appropriate ones
diff --git a/Documentation/x86_64/kernel-stacks b/Documentation/x86_64/kernel-stacks
new file mode 100644 (file)
index 0000000..bddfddd
--- /dev/null
@@ -0,0 +1,99 @@
+Most of the text from Keith Owens, hacked by AK
+
+x86_64 page size (PAGE_SIZE) is 4K.
+
+Like all other architectures, x86_64 has a kernel stack for every
+active thread.  These thread stacks are THREAD_SIZE (2*PAGE_SIZE) big.
+These stacks contain useful data as long as a thread is alive or a
+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
+
+* Interrupt stack.  IRQSTACKSIZE
+
+  Used for external hardware interrupts.  If this is the first external
+  hardware interrupt (i.e. not a nested hardware interrupt) then the
+  kernel switches from the current task to the interrupt stack.  Like
+  the split thread and interrupt stacks on i386 (with CONFIG_4KSTACKS),
+  this gives more room for kernel interrupt processing without having
+  to increase the size of every per thread stack.
+
+  The interrupt stack is also used when processing a softirq.
+
+Switching to the kernel interrupt stack is done by software based on a
+per CPU interrupt nest counter. This is needed because x86-64 "IST"
+hardware stacks cannot nest without races.
+
+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.
+
+An IST is selected by an 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)
+
+Events with different IST codes (i.e. with different stacks) can be
+nested.  For example, a debug interrupt can safely be interrupted by an
+NMI.  arch/x86_64/kernel/entry.S::paranoidentry adjusts the stack
+pointers on entry to and exit from all IST events, in theory allowing
+IST events with the same code to be nested.  However in most cases, the
+stack size allocated to an IST assumes no nesting for the same code.
+If that assumption is ever broken then the stacks will become corrupt.
+
+The currently assigned IST stacks are :-
+
+* STACKFAULT_STACK.  EXCEPTION_STKSZ (PAGE_SIZE).
+
+  Used for interrupt 12 - Stack Fault Exception (#SS).
+
+  This allows 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.
+
+* NMI_STACK.  EXCEPTION_STKSZ (PAGE_SIZE).
+
+  Used for non-maskable interrupts (NMI).
+
+  NMI can be delivered at any time, including when the kernel is in the
+  middle of switching stacks.  Using IST for NMI events avoids making
+  assumptions about the previous state of the kernel stack.
+
+* DEBUG_STACK.  DEBUG_STKSZ
+
+  Used for hardware debug interrupts (interrupt 1) and for software
+  debug interrupts (INT3).
+
+  When debugging a kernel, debug interrupts (both hardware and
+  software) can occur at any time.  Using IST for these interrupts
+  avoids making assumptions about the previous state of the kernel
+  stack.
+
+* MCE_STACK.  EXCEPTION_STKSZ (PAGE_SIZE).
+
+  Used for interrupt 18 - Machine Check Exception (#MC).
+
+  MCE can be delivered at any time, including when the kernel is in the
+  middle of switching stacks.  Using IST for MCE events avoids making
+  assumptions about the previous state of the kernel stack.
+
+For more details see the Intel IA32 or AMD AMD64 architecture manuals.
index 767a43434ae80fa6940c36b6cf6799dddb85270c..63673e6513b717994de75ffb552f546f3c140ab8 100644 (file)
@@ -2679,7 +2679,6 @@ M:        josejx@gentoo.org
 P:     Daniel Drake
 M:     dsd@gentoo.org
 W:     http://softmac.sipsolutions.net/
-L:     softmac-dev@sipsolutions.net
 L:     netdev@vger.kernel.org
 S:     Maintained
 
index 80dac0245d6647459857617dcbb02b693ee832d1..4c6c5e32ef96e3d12da975e682ee8a3f6ebc37e3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1385,9 +1385,13 @@ endif #ifeq ($(config-targets),1)
 endif #ifeq ($(mixed-targets),1)
 
 PHONY += checkstack kernelrelease kernelversion
+
+# Use $(SUBARCH) here instead of $(ARCH) so that this works for UML.
+# In the UML case, $(SUBARCH) is the name of the underlying
+# architecture, while for all other arches, it is the same as $(ARCH).
 checkstack:
        $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
-       $(PERL) $(src)/scripts/checkstack.pl $(ARCH)
+       $(PERL) $(src)/scripts/checkstack.pl $(SUBARCH)
 
 kernelrelease:
        $(if $(wildcard include/config/kernel.release), $(Q)echo $(KERNELRELEASE), \
index cce26576999ea8333a89a132f622edbe01185928..337c01c4ac37194860c45f845a503686ecc0e6c4 100644 (file)
@@ -284,21 +284,9 @@ static struct pxaficp_platform_data corgi_ficp_platform_data = {
 /*
  * USB Device Controller
  */
-static void corgi_udc_command(int cmd)
-{
-       switch(cmd)     {
-       case PXA2XX_UDC_CMD_CONNECT:
-               GPSR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
-               break;
-       case PXA2XX_UDC_CMD_DISCONNECT:
-               GPCR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
-               break;
-       }
-}
-
 static struct pxa2xx_udc_mach_info udc_info __initdata = {
        /* no connect GPIO; corgi can't tell connection status */
-       .udc_command            = corgi_udc_command,
+       .gpio_pullup            = CORGI_GPIO_USB_PULLUP,
 };
 
 
@@ -350,7 +338,6 @@ static void __init corgi_init(void)
        corgi_ssp_set_machinfo(&corgi_ssp_machinfo);
 
        pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT);
-       pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
        pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
 
        pxa_set_udc_info(&udc_info);
index 9b815327b6a58f2c23db3100a909fab29884ac5b..7e8096809be2bc227ef4e8acb310455a92d8cbfb 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
index 5d0523bbe298ad2082b3e0df33c011dae9fc7900..7b073052203d77a4d6002709b53f435afda0a10b 100644 (file)
@@ -15,7 +15,8 @@
 
 void show_dtlb_entry(unsigned int index)
 {
-       unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save, flags;
+       unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save;
+       unsigned long flags;
 
        local_irq_save(flags);
        mmucr_save = sysreg_read(MMUCR);
@@ -305,7 +306,8 @@ static void tlb_stop(struct seq_file *tlb, void *v)
 
 static int tlb_show(struct seq_file *tlb, void *v)
 {
-       unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save, flags;
+       unsigned int tlbehi, tlbehi_save, tlbelo, mmucr, mmucr_save;
+       unsigned long flags;
        unsigned long *index = v;
 
        if (*index == 0)
index 6189b0c28d6f5d24330bdfb396ae3ad9caf47ede..3fd2f256f2be3402cea23aa3a93a21c0c161197a 100644 (file)
@@ -166,7 +166,6 @@ config X86_VISWS
 
 config X86_GENERICARCH
        bool "Generic architecture (Summit, bigsmp, ES7000, default)"
-       depends on SMP
        help
           This option compiles in the Summit, bigsmp, ES7000, default subarchitectures.
          It is intended for a generic binary kernel.
@@ -263,7 +262,7 @@ source "kernel/Kconfig.preempt"
 
 config X86_UP_APIC
        bool "Local APIC support on uniprocessors"
-       depends on !SMP && !(X86_VISWS || X86_VOYAGER)
+       depends on !SMP && !(X86_VISWS || X86_VOYAGER || X86_GENERICARCH)
        help
          A local APIC (Advanced Programmable Interrupt Controller) is an
          integrated interrupt controller in the CPU. If you have a single-CPU
@@ -288,12 +287,12 @@ config X86_UP_IOAPIC
 
 config X86_LOCAL_APIC
        bool
-       depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER)
+       depends on X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH
        default y
 
 config X86_IO_APIC
        bool
-       depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER))
+       depends on X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH
        default y
 
 config X86_VISWS_APIC
@@ -402,6 +401,7 @@ config X86_REBOOTFIXUPS
 
 config MICROCODE
        tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
+       select FW_LOADER
        ---help---
          If you say Y here and also to "/dev file system support" in the
          'File systems' section, you will be able to update the microcode on
@@ -417,6 +417,11 @@ config MICROCODE
          To compile this driver as a module, choose M here: the
          module will be called microcode.
 
+config MICROCODE_OLD_INTERFACE
+       bool
+       depends on MICROCODE
+       default y
+
 config X86_MSR
        tristate "/dev/cpu/*/msr - Model-specific register support"
        help
@@ -599,12 +604,10 @@ config ARCH_SELECT_MEMORY_MODEL
        def_bool y
        depends on ARCH_SPARSEMEM_ENABLE
 
-source "mm/Kconfig"
+config ARCH_POPULATES_NODE_MAP
+       def_bool y
 
-config HAVE_ARCH_EARLY_PFN_TO_NID
-       bool
-       default y
-       depends on NUMA
+source "mm/Kconfig"
 
 config HIGHPTE
        bool "Allocate 3rd-level pagetables from highmem"
@@ -741,8 +744,7 @@ config SECCOMP
 source kernel/Kconfig.hz
 
 config KEXEC
-       bool "kexec system call (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       bool "kexec system call"
        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
@@ -763,6 +765,13 @@ config CRASH_DUMP
        depends on HIGHMEM
        help
          Generate crash dump after being started by kexec.
+          This should be normally only set in special crash dump kernels
+         which are loaded in the main kernel with kexec-tools into
+         a specially reserved region and then later executed after
+         a crash by kdump/kexec. The crash dump kernel must be compiled
+          to a memory address not used by the main kernel or BIOS using
+          PHYSICAL_START.
+         For more details see Documentation/kdump/kdump.txt
 
 config PHYSICAL_START
        hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
index 3e4adb1e224430ce3398ff538c09d316522b5ab2..7cc0b189b82baa80d83d813a11ec256243a6cb0c 100644 (file)
@@ -46,6 +46,14 @@ cflags-y += -ffreestanding
 # a lot more stack due to the lack of sharing of stacklots:
 CFLAGS                         += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;)
 
+# do binutils support CFI?
+cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+
+# is .cfi_signal_frame supported too?
+cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+
 CFLAGS += $(cflags-y)
 
 # Default subarch .c files
index 4b84ea216f2b81ede738e80206a5fafd8e5ef994..34321368011ac7b2aadf6111f37d038c274609a8 100644 (file)
 #include <asm/setup.h>
 
 #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+
+# It is assumed that %ds == INITSEG here
+
        movb    $0, (EDD_MBR_SIG_NR_BUF)
        movb    $0, (EDDNR)
 
-# Check the command line for two options:
+# Check the command line for options:
 # edd=of  disables EDD completely  (edd=off)
 # edd=sk  skips the MBR test    (edd=skipmbr)
+# edd=on  re-enables EDD (edd=on)
+
        pushl   %esi
-       cmpl    $0, %cs:cmd_line_ptr
-       jz      done_cl
+       movw    $edd_mbr_sig_start, %di # Default to edd=on
+
        movl    %cs:(cmd_line_ptr), %esi
-# ds:esi has the pointer to the command line now
-       movl    $(COMMAND_LINE_SIZE-7), %ecx
-# loop through kernel command line one byte at a time
-cl_loop:
-       cmpl    $EDD_CL_EQUALS, (%si)
+       andl    %esi, %esi
+       jz      old_cl                  # Old boot protocol?
+
+# Convert to a real-mode pointer in fs:si
+       movl    %esi, %eax
+       shrl    $4, %eax
+       movw    %ax, %fs
+       andw    $0xf, %si
+       jmp     have_cl_pointer
+
+# Old-style boot protocol?
+old_cl:
+       push    %ds                     # aka INITSEG
+       pop     %fs
+
+       cmpw    $0xa33f, (0x20)
+       jne     done_cl                 # No command line at all?
+       movw    (0x22), %si             # Pointer relative to INITSEG
+
+# fs:si has the pointer to the command line now
+have_cl_pointer:
+
+# Loop through kernel command line one byte at a time.  Just in
+# case the loader is buggy and failed to null-terminate the command line
+# terminate if we get close enough to the end of the segment that we
+# cannot fit "edd=XX"...
+cl_atspace:
+       cmpw    $-5, %si                # Watch for segment wraparound
+       jae     done_cl
+       movl    %fs:(%si), %eax
+       andb    %al, %al                # End of line?
+       jz      done_cl
+       cmpl    $EDD_CL_EQUALS, %eax
        jz      found_edd_equals
-       incl    %esi
-       loop    cl_loop
-       jmp     done_cl
+       cmpb    $0x20, %al              # <= space consider whitespace
+       ja      cl_skipword
+       incw    %si
+       jmp     cl_atspace
+
+cl_skipword:
+       cmpw    $-5, %si                # Watch for segment wraparound
+       jae     done_cl
+       movb    %fs:(%si), %al          # End of string?
+       andb    %al, %al
+       jz      done_cl
+       cmpb    $0x20, %al
+       jbe     cl_atspace
+       incw    %si
+       jmp     cl_skipword
+
 found_edd_equals:
 # only looking at first two characters after equals
-       addl    $4, %esi
-       cmpw    $EDD_CL_OFF, (%si)      # edd=of
-       jz      do_edd_off
-       cmpw    $EDD_CL_SKIP, (%si)     # edd=sk
-       jz      do_edd_skipmbr
-       jmp     done_cl
+# late overrides early on the command line, so keep going after finding something
+       movw    %fs:4(%si), %ax
+       cmpw    $EDD_CL_OFF, %ax        # edd=of
+       je      do_edd_off
+       cmpw    $EDD_CL_SKIP, %ax       # edd=sk
+       je      do_edd_skipmbr
+       cmpw    $EDD_CL_ON, %ax         # edd=on
+       je      do_edd_on
+       jmp     cl_skipword
 do_edd_skipmbr:
-       popl    %esi
-       jmp     edd_start
+       movw    $edd_start, %di
+       jmp     cl_skipword
 do_edd_off:
-       popl    %esi
-       jmp     edd_done
+       movw    $edd_done, %di
+       jmp     cl_skipword
+do_edd_on:
+       movw    $edd_mbr_sig_start, %di
+       jmp     cl_skipword
+
 done_cl:
        popl    %esi
-
+       jmpw    *%di
 
 # Read the first sector of each BIOS disk device and store the 4-byte signature
 edd_mbr_sig_start:
index d2b684cd620ae63888bbb54c06721d0b4fe8e5e5..3aec4538a113b9f84d33c3613e7137e18aaa8f61 100644 (file)
@@ -494,12 +494,12 @@ no_voyager:
        movw    %cs, %ax                        # aka SETUPSEG
        subw    $DELTA_INITSEG, %ax             # aka INITSEG
        movw    %ax, %ds
-       movw    $0, (0x1ff)                     # default is no pointing device
+       movb    $0, (0x1ff)                     # default is no pointing device
        int     $0x11                           # int 0x11: equipment list
        testb   $0x04, %al                      # check if mouse installed
        jz      no_psmouse
 
-       movw    $0xAA, (0x1ff)                  # device present
+       movb    $0xAA, (0x1ff)                  # device present
 no_psmouse:
 
 #if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
index 89ebb7a316abfc86a31bbeb83c6455efc369271d..1a29bfa26d0cbf4ddf54a5d7e98661f5ecf91e74 100644 (file)
@@ -1,41 +1,51 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.18-git5
+# Tue Sep 26 09:30:47 2006
 #
 CONFIG_X86_32=y
+CONFIG_GENERIC_TIME=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_SEMAPHORE_SLEEPERS=y
 CONFIG_X86=y
 CONFIG_MMU=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_HWEIGHT=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_DMI=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
 #
 CONFIG_LOCALVERSION=""
-# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
-CONFIG_VM86=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=y
 CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
@@ -45,11 +55,9 @@ CONFIG_BASE_FULL=y
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
 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
@@ -60,41 +68,45 @@ CONFIG_BASE_SMALL=0
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 # CONFIG_KMOD is not set
+CONFIG_STOP_MACHINE=y
 
 #
 # Block layer
 #
-# CONFIG_LBD is not set
+CONFIG_LBD=y
+# 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_AS=y
+CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_AS=y
 # CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_CFQ is not set
 # CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_DEFAULT_IOSCHED="anticipatory"
 
 #
 # Processor type and features
 #
-CONFIG_X86_PC=y
+CONFIG_SMP=y
+# CONFIG_X86_PC is not set
 # CONFIG_X86_ELAN is not set
 # CONFIG_X86_VOYAGER is not set
 # CONFIG_X86_NUMAQ is not set
 # CONFIG_X86_SUMMIT is not set
 # CONFIG_X86_BIGSMP is not set
 # CONFIG_X86_VISWS is not set
-# CONFIG_X86_GENERICARCH is not set
+CONFIG_X86_GENERICARCH=y
 # CONFIG_X86_ES7000 is not set
+CONFIG_X86_CYCLONE_TIMER=y
 # CONFIG_M386 is not set
 # CONFIG_M486 is not set
 # CONFIG_M586 is not set
@@ -102,11 +114,11 @@ CONFIG_X86_PC=y
 # CONFIG_M586MMX is not set
 # CONFIG_M686 is not set
 # CONFIG_MPENTIUMII is not set
-# CONFIG_MPENTIUMIII is not set
+CONFIG_MPENTIUMIII=y
 # CONFIG_MPENTIUMM is not set
 # CONFIG_MPENTIUM4 is not set
 # CONFIG_MK6 is not set
-CONFIG_MK7=y
+# CONFIG_MK7 is not set
 # CONFIG_MK8 is not set
 # CONFIG_MCRUSOE is not set
 # CONFIG_MEFFICEON is not set
@@ -117,10 +129,10 @@ CONFIG_MK7=y
 # CONFIG_MGEODE_LX is not set
 # CONFIG_MCYRIXIII is not set
 # CONFIG_MVIAC3_2 is not set
-# CONFIG_X86_GENERIC is not set
+CONFIG_X86_GENERIC=y
 CONFIG_X86_CMPXCHG=y
 CONFIG_X86_XADD=y
-CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_SHIFT=7
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_X86_WP_WORKS_OK=y
@@ -131,26 +143,28 @@ CONFIG_X86_CMPXCHG64=y
 CONFIG_X86_GOOD_APIC=y
 CONFIG_X86_INTEL_USERCOPY=y
 CONFIG_X86_USE_PPRO_CHECKSUM=y
-CONFIG_X86_USE_3DNOW=y
 CONFIG_X86_TSC=y
-# CONFIG_HPET_TIMER is not set
-# CONFIG_SMP is not set
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_HPET_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
+CONFIG_NR_CPUS=32
+CONFIG_SCHED_SMT=y
+CONFIG_SCHED_MC=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
 # CONFIG_PREEMPT is not set
-CONFIG_X86_UP_APIC=y
-CONFIG_X86_UP_IOAPIC=y
+CONFIG_PREEMPT_BKL=y
 CONFIG_X86_LOCAL_APIC=y
 CONFIG_X86_IO_APIC=y
 CONFIG_X86_MCE=y
 CONFIG_X86_MCE_NONFATAL=y
-# CONFIG_X86_MCE_P4THERMAL is not set
+CONFIG_X86_MCE_P4THERMAL=y
+CONFIG_VM86=y
 # CONFIG_TOSHIBA is not set
 # CONFIG_I8K is not set
 # CONFIG_X86_REBOOTFIXUPS is not set
-# CONFIG_MICROCODE is not set
-# CONFIG_X86_MSR is not set
-# CONFIG_X86_CPUID is not set
+CONFIG_MICROCODE=y
+CONFIG_X86_MSR=y
+CONFIG_X86_CPUID=y
 
 #
 # Firmware Drivers
@@ -158,68 +172,67 @@ CONFIG_X86_MCE_NONFATAL=y
 # CONFIG_EDD is not set
 # CONFIG_DELL_RBU is not set
 # CONFIG_DCDBAS is not set
-CONFIG_NOHIGHMEM=y
-# CONFIG_HIGHMEM4G is not set
+# CONFIG_NOHIGHMEM is not set
+CONFIG_HIGHMEM4G=y
 # CONFIG_HIGHMEM64G is not set
-CONFIG_VMSPLIT_3G=y
-# CONFIG_VMSPLIT_3G_OPT is not set
-# CONFIG_VMSPLIT_2G is not set
-# CONFIG_VMSPLIT_1G is not set
 CONFIG_PAGE_OFFSET=0xC0000000
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_ARCH_SPARSEMEM_ENABLE=y
-CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_HIGHMEM=y
 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=y
+# CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_RESOURCES_64BIT=y
+# CONFIG_HIGHPTE is not set
 # CONFIG_MATH_EMULATION is not set
 CONFIG_MTRR=y
 # CONFIG_EFI is not set
+# CONFIG_IRQBALANCE is not set
 CONFIG_REGPARM=y
-# CONFIG_SECCOMP is not set
-CONFIG_HZ_100=y
-# CONFIG_HZ_250 is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
 # CONFIG_HZ_1000 is not set
-CONFIG_HZ=100
+CONFIG_HZ=250
 # CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
 CONFIG_PHYSICAL_START=0x100000
-CONFIG_DOUBLEFAULT=y
+# CONFIG_HOTPLUG_CPU is not set
+CONFIG_COMPAT_VDSO=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
 
 #
 # Power management options (ACPI, APM)
 #
 CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
+CONFIG_PM_LEGACY=y
 # CONFIG_PM_DEBUG is not set
-CONFIG_SOFTWARE_SUSPEND=y
-CONFIG_PM_STD_PARTITION=""
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
 #
 CONFIG_ACPI=y
-# CONFIG_ACPI_SLEEP is not set
-# CONFIG_ACPI_AC is not set
-# CONFIG_ACPI_BATTERY is not set
-# CONFIG_ACPI_BUTTON is not set
+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 is not set
-# CONFIG_ACPI_PROCESSOR is not set
+CONFIG_ACPI_FAN=y
+# CONFIG_ACPI_DOCK is not set
+CONFIG_ACPI_PROCESSOR=y
+CONFIG_ACPI_THERMAL=y
 # CONFIG_ACPI_ASUS is not set
 # CONFIG_ACPI_IBM is not set
 # CONFIG_ACPI_TOSHIBA is not set
-CONFIG_ACPI_BLACKLIST_YEAR=0
-# CONFIG_ACPI_DEBUG is not set
+CONFIG_ACPI_BLACKLIST_YEAR=2001
+CONFIG_ACPI_DEBUG=y
 CONFIG_ACPI_EC=y
 CONFIG_ACPI_POWER=y
 CONFIG_ACPI_SYSTEM=y
-# CONFIG_X86_PM_TIMER is not set
+CONFIG_X86_PM_TIMER=y
 # CONFIG_ACPI_CONTAINER is not set
 
 #
@@ -230,7 +243,41 @@ CONFIG_ACPI_SYSTEM=y
 #
 # CPU Frequency scaling
 #
-# CONFIG_CPU_FREQ is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
+CONFIG_CPU_FREQ_DEBUG=y
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+#
+# CPUFreq processor drivers
+#
+CONFIG_X86_ACPI_CPUFREQ=y
+# CONFIG_X86_POWERNOW_K6 is not set
+# CONFIG_X86_POWERNOW_K7 is not set
+CONFIG_X86_POWERNOW_K8=y
+CONFIG_X86_POWERNOW_K8_ACPI=y
+# CONFIG_X86_GX_SUSPMOD is not set
+# CONFIG_X86_SPEEDSTEP_CENTRINO is not set
+# CONFIG_X86_SPEEDSTEP_ICH is not set
+# CONFIG_X86_SPEEDSTEP_SMI is not set
+# CONFIG_X86_P4_CLOCKMOD is not set
+# CONFIG_X86_CPUFREQ_NFORCE2 is not set
+# CONFIG_X86_LONGRUN is not set
+# CONFIG_X86_LONGHAUL is not set
+
+#
+# shared options
+#
+CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
+# CONFIG_X86_SPEEDSTEP_LIB is not set
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
@@ -244,12 +291,13 @@ CONFIG_PCI_BIOS=y
 CONFIG_PCI_DIRECT=y
 CONFIG_PCI_MMCONFIG=y
 # CONFIG_PCIEPORTBUS is not set
-# CONFIG_PCI_MSI is not set
-# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
 CONFIG_ISA_DMA_API=y
 # CONFIG_ISA is not set
 # CONFIG_MCA is not set
 # CONFIG_SCx200 is not set
+CONFIG_K8_NB=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -278,93 +326,54 @@ CONFIG_NET=y
 #
 # CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
+# CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_FIB_HASH=y
-# CONFIG_IP_PNP is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE 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_DIAG is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# Core Netfilter Configuration
-#
-# CONFIG_NETFILTER_NETLINK is not set
-CONFIG_NETFILTER_XTABLES=y
-# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
-# CONFIG_NETFILTER_XT_TARGET_MARK is not set
-# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
-# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
-# CONFIG_NETFILTER_XT_MATCH_CONNTRACK is not set
-# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
-# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
-# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
-CONFIG_NETFILTER_XT_MATCH_LIMIT=y
-CONFIG_NETFILTER_XT_MATCH_MAC=y
-# CONFIG_NETFILTER_XT_MATCH_MARK is not set
-# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
-# CONFIG_NETFILTER_XT_MATCH_REALM is not set
-# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
-CONFIG_NETFILTER_XT_MATCH_STATE=y
-# CONFIG_NETFILTER_XT_MATCH_STRING is not set
-# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=y
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=y
-# CONFIG_IP_NF_IRC is not set
-# CONFIG_IP_NF_NETBIOS_NS is not set
-# CONFIG_IP_NF_TFTP is not set
-# CONFIG_IP_NF_AMANDA is not set
-# CONFIG_IP_NF_PPTP is not set
-# CONFIG_IP_NF_QUEUE is not set
-CONFIG_IP_NF_IPTABLES=y
-# CONFIG_IP_NF_MATCH_IPRANGE is not set
-# CONFIG_IP_NF_MATCH_MULTIPORT is not set
-# CONFIG_IP_NF_MATCH_TOS is not set
-# CONFIG_IP_NF_MATCH_RECENT is not set
-# CONFIG_IP_NF_MATCH_ECN is not set
-# CONFIG_IP_NF_MATCH_DSCP is not set
-# CONFIG_IP_NF_MATCH_AH_ESP is not set
-# CONFIG_IP_NF_MATCH_TTL is not set
-# CONFIG_IP_NF_MATCH_OWNER is not set
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
-CONFIG_IP_NF_FILTER=y
-# CONFIG_IP_NF_TARGET_REJECT is not set
-CONFIG_IP_NF_TARGET_LOG=y
-# CONFIG_IP_NF_TARGET_ULOG is not set
-# CONFIG_IP_NF_TARGET_TCPMSS is not set
-# CONFIG_IP_NF_NAT is not set
-# CONFIG_IP_NF_MANGLE is not set
-# CONFIG_IP_NF_RAW is not set
-# CONFIG_IP_NF_ARPTABLES is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+CONFIG_IPV6=y
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
 
 #
 # DCCP Configuration (EXPERIMENTAL)
@@ -389,7 +398,6 @@ CONFIG_IP_NF_TARGET_LOG=y
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -402,6 +410,7 @@ CONFIG_IP_NF_TARGET_LOG=y
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NET_TCPPROBE is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
@@ -416,7 +425,9 @@ CONFIG_IP_NF_TARGET_LOG=y
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
@@ -431,13 +442,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 #
 # Parallel port support
 #
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
-# CONFIG_PARPORT_SERIAL is not set
-# CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_GSC is not set
-CONFIG_PARPORT_1284=y
+# CONFIG_PARPORT is not set
 
 #
 # Plug and Play support
@@ -447,8 +452,7 @@ CONFIG_PARPORT_1284=y
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_PARIDE is not set
+CONFIG_BLK_DEV_FD=y
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
@@ -459,8 +463,11 @@ CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
-# CONFIG_BLK_DEV_RAM 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
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -476,7 +483,7 @@ CONFIG_BLK_DEV_IDE=y
 # CONFIG_BLK_DEV_IDE_SATA is not set
 # CONFIG_BLK_DEV_HD_IDE is not set
 CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDEDISK_MULTI_MODE=y
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -486,10 +493,10 @@ CONFIG_BLK_DEV_IDECD=y
 #
 # IDE chipset support/bugfixes
 #
-# CONFIG_IDE_GENERIC is not set
+CONFIG_IDE_GENERIC=y
 # CONFIG_BLK_DEV_CMD640 is not set
 CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
 # CONFIG_BLK_DEV_OFFBOARD is not set
 # CONFIG_BLK_DEV_GENERIC is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
@@ -500,7 +507,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_AMD74XX=y
 # CONFIG_BLK_DEV_ATIIXP is not set
 # CONFIG_BLK_DEV_CMD64X is not set
 # CONFIG_BLK_DEV_TRIFLEX is not set
@@ -511,7 +518,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_BLK_DEV_HPT366 is not set
 # CONFIG_BLK_DEV_SC1200 is not set
-# CONFIG_BLK_DEV_PIIX is not set
+CONFIG_BLK_DEV_PIIX=y
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -521,7 +528,7 @@ CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
-CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_BLK_DEV_VIA82CXXX is not set
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -533,6 +540,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
 # CONFIG_SCSI_PROC_FS is not set
 
 #
@@ -541,8 +549,9 @@ CONFIG_SCSI=y
 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_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=y
 # CONFIG_CHR_DEV_SCH is not set
 
 #
@@ -553,29 +562,44 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOGGING is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
 # 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_BLK_DEV_3W_XXXX_RAID=y
 # 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=y
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+CONFIG_AIC7XXX_RESET_DELAY_MS=5000
+CONFIG_AIC7XXX_DEBUG_ENABLE=y
+CONFIG_AIC7XXX_DEBUG_MASK=0
+CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
+CONFIG_SCSI_AIC79XX=y
+CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+CONFIG_AIC79XX_RESET_DELAY_MS=4000
+# CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+# CONFIG_AIC79XX_DEBUG_ENABLE is not set
+CONFIG_AIC79XX_DEBUG_MASK=0
+# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_AIC94XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS 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_SATA is not set
+# CONFIG_SCSI_HPTIOP is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -584,11 +608,9 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM 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_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -597,23 +619,115 @@ CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_SVW=y
+CONFIG_ATA_PIIX=y
+# CONFIG_SATA_MV is not set
+CONFIG_SATA_NV=y
+# 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=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+CONFIG_SATA_VIA=y
+# CONFIG_SATA_VITESSE is not set
+CONFIG_SATA_INTEL_COMBINED=y
+# 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_CS5535 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_JMICRON is not set
+# CONFIG_PATA_LEGACY is not set
+# CONFIG_PATA_TRIFLEX 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_QDI 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
+
 #
 # Multi-device support (RAID and LVM)
 #
-# CONFIG_MD is not set
+CONFIG_MD=y
+# CONFIG_BLK_DEV_MD is not set
+CONFIG_BLK_DEV_DM=y
+# CONFIG_DM_CRYPT is not set
+# CONFIG_DM_SNAPSHOT is not set
+# CONFIG_DM_MIRROR is not set
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
 
 #
 # Fusion MPT device support
 #
-# CONFIG_FUSION is not set
-# CONFIG_FUSION_SPI is not set
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
 # CONFIG_FUSION_FC is not set
 # CONFIG_FUSION_SAS is not set
+CONFIG_FUSION_MAX_SGE=128
+# CONFIG_FUSION_CTL is not set
 
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
+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
+#
+
+#
+# Texas Instruments PCILynx requires I2C
+#
+CONFIG_IEEE1394_OHCI1394=y
+
+#
+# Protocol Drivers
+#
+# CONFIG_IEEE1394_VIDEO1394 is not set
+# CONFIG_IEEE1394_SBP2 is not set
+# CONFIG_IEEE1394_ETH1394 is not set
+# CONFIG_IEEE1394_DV1394 is not set
+CONFIG_IEEE1394_RAWIO=y
 
 #
 # I2O device support
@@ -652,46 +766,63 @@ CONFIG_MII=y
 #
 # Tulip family network device support
 #
-# CONFIG_NET_TULIP is not set
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
 # CONFIG_HP100 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
+CONFIG_B44=y
+CONFIG_FORCEDETH=y
+# CONFIG_FORCEDETH_NAPI is not set
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 CONFIG_E100=y
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
+CONFIG_8139CP=y
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
 #
 # CONFIG_ACENIC is not set
 # CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
+CONFIG_E1000=y
+# CONFIG_E1000_NAPI is not set
+# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
 # CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
+CONFIG_SKY2=y
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
+CONFIG_TIGON3=y
+CONFIG_BNX2=y
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -699,6 +830,7 @@ CONFIG_E100=y
 # CONFIG_CHELSIO_T1 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
 
 #
 # Token Ring devices
@@ -716,14 +848,15 @@ CONFIG_E100=y
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-# CONFIG_PLIP 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
-# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
 
 #
 # ISDN subsystem
@@ -745,8 +878,8 @@ CONFIG_INPUT=y
 #
 CONFIG_INPUT_MOUSEDEV=y
 CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
 CONFIG_INPUT_EVDEV=y
@@ -776,7 +909,6 @@ CONFIG_SERIO=y
 CONFIG_SERIO_I8042=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
 # CONFIG_SERIO_PCIPS2 is not set
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
@@ -788,14 +920,15 @@ CONFIG_SERIO_LIBPS2=y
 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 is not set
-# CONFIG_SERIAL_8250_ACPI is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
 CONFIG_SERIAL_8250_NR_UARTS=4
 CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
@@ -804,14 +937,11 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_PRINTER=y
-# CONFIG_LP_CONSOLE is not set
-# CONFIG_PPDEV is not set
-# CONFIG_TIPAR is not set
 
 #
 # IPMI
@@ -822,8 +952,12 @@ CONFIG_PRINTER=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_NVRAM=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_INTEL=y
+CONFIG_HW_RANDOM_AMD=y
+CONFIG_HW_RANDOM_GEODE=y
+CONFIG_HW_RANDOM_VIA=y
+# CONFIG_NVRAM is not set
 CONFIG_RTC=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -833,31 +967,28 @@ CONFIG_RTC=y
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
 CONFIG_AGP=y
 # CONFIG_AGP_ALI is not set
 # CONFIG_AGP_ATI is not set
 # CONFIG_AGP_AMD is not set
-# CONFIG_AGP_AMD64 is not set
-# CONFIG_AGP_INTEL is not set
+CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
 # CONFIG_AGP_NVIDIA is not set
 # CONFIG_AGP_SIS is not set
 # CONFIG_AGP_SWORKS is not set
-CONFIG_AGP_VIA=y
+# CONFIG_AGP_VIA is not set
 # CONFIG_AGP_EFFICEON is not set
-CONFIG_DRM=y
-# CONFIG_DRM_TDFX is not set
-# CONFIG_DRM_R128 is not set
-CONFIG_DRM_RADEON=y
-# CONFIG_DRM_MGA is not set
-# CONFIG_DRM_SIS is not set
-# CONFIG_DRM_VIA is not set
-# CONFIG_DRM_SAVAGE is not set
+# CONFIG_DRM is not set
 # CONFIG_MWAVE is not set
+# CONFIG_PC8736x_GPIO is not set
+# CONFIG_NSC_GPIO is not set
 # CONFIG_CS5535_GPIO is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HPET is not set
-# CONFIG_HANGCHECK_TIMER is not set
+CONFIG_RAW_DRIVER=y
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_HPET=y
+# CONFIG_HPET_RTC_IRQ is not set
+CONFIG_HPET_MMAP=y
+CONFIG_HANGCHECK_TIMER=y
 
 #
 # TPM devices
@@ -868,59 +999,7 @@ CONFIG_DRM_RADEON=y
 #
 # I2C support
 #
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-
-#
-# I2C Algorithms
-#
-CONFIG_I2C_ALGOBIT=y
-# CONFIG_I2C_ALGOPCF is not set
-# CONFIG_I2C_ALGOPCA is not set
-
-#
-# I2C Hardware Bus support
-#
-# CONFIG_I2C_ALI1535 is not set
-# CONFIG_I2C_ALI1563 is not set
-# CONFIG_I2C_ALI15X3 is not set
-# CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
-# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
-# CONFIG_I2C_PIIX4 is not set
-CONFIG_I2C_ISA=y
-# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_PARPORT is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_SCx200_ACB is not set
-# CONFIG_I2C_SIS5595 is not set
-# CONFIG_I2C_SIS630 is not set
-# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_VIA is not set
-CONFIG_I2C_VIAPRO=y
-# CONFIG_I2C_VOODOO3 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_RTC8564 is not set
-# CONFIG_SENSORS_MAX6875 is not set
-# CONFIG_RTC_X1205_I2C 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
+# CONFIG_I2C is not set
 
 #
 # SPI support
@@ -931,169 +1010,44 @@ CONFIG_I2C_VIAPRO=y
 #
 # Dallas's 1-wire bus
 #
-# CONFIG_W1 is not set
 
 #
 # Hardware Monitoring support
 #
-CONFIG_HWMON=y
-CONFIG_HWMON_VID=y
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_FSCHER is not set
-# CONFIG_SENSORS_FSCPOS is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-CONFIG_SENSORS_IT87=y
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_SIS5595 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_VIA686A is not set
-# CONFIG_SENSORS_VT8231 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_SENSORS_HDAPS is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
 
 #
 # Misc devices
 #
 # CONFIG_IBM_ASM is not set
 
-#
-# Multimedia Capabilities Port drivers
-#
-
 #
 # Multimedia devices
 #
-CONFIG_VIDEO_DEV=y
-
-#
-# Video For Linux
-#
-
-#
-# Video Adapters
-#
-# CONFIG_VIDEO_ADV_DEBUG is not set
-# CONFIG_VIDEO_BT848 is not set
-# CONFIG_VIDEO_BWQCAM is not set
-# CONFIG_VIDEO_CQCAM is not set
-# CONFIG_VIDEO_W9966 is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_VIDEO_SAA5246A is not set
-# CONFIG_VIDEO_SAA5249 is not set
-# CONFIG_TUNER_3036 is not set
-# CONFIG_VIDEO_STRADIS is not set
-# CONFIG_VIDEO_ZORAN is not set
-CONFIG_VIDEO_SAA7134=y
-# CONFIG_VIDEO_SAA7134_ALSA is not set
-# CONFIG_VIDEO_MXB is not set
-# CONFIG_VIDEO_DPC is not set
-# CONFIG_VIDEO_HEXIUM_ORION is not set
-# CONFIG_VIDEO_HEXIUM_GEMINI is not set
-# CONFIG_VIDEO_CX88 is not set
-# CONFIG_VIDEO_EM28XX is not set
-# CONFIG_VIDEO_OVCAMCHIP is not set
-# CONFIG_VIDEO_AUDIO_DECODER is not set
-# CONFIG_VIDEO_DECODER is not set
-
-#
-# Radio Adapters
-#
-# CONFIG_RADIO_GEMTEK_PCI is not set
-# CONFIG_RADIO_MAXIRADIO is not set
-# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
 
 #
 # Digital Video Broadcasting Devices
 #
 # CONFIG_DVB is not set
-CONFIG_VIDEO_TUNER=y
-CONFIG_VIDEO_BUF=y
-CONFIG_VIDEO_IR=y
+# CONFIG_USB_DABUSB is not set
 
 #
 # Graphics support
 #
-CONFIG_FB=y
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_MACMODES is not set
-CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ARC is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_VGA16 is not set
-# CONFIG_FB_VESA is not set
-CONFIG_VIDEO_SELECT=y
-# CONFIG_FB_HGA is not set
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_NVIDIA is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_I810 is not set
-# CONFIG_FB_INTEL is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
-CONFIG_FB_RADEON=y
-CONFIG_FB_RADEON_I2C=y
-# CONFIG_FB_RADEON_DEBUG is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SAVAGE is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-# CONFIG_FB_KYRO is not set
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_CYBLA is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_GEODE is not set
-# CONFIG_FB_VIRTUAL is not set
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB is not set
 
 #
 # Console display driver support
 #
 CONFIG_VGA_CONSOLE=y
+CONFIG_VGACON_SOFT_SCROLLBACK=y
+CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=128
+CONFIG_VIDEO_SELECT=y
 CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
-# CONFIG_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
 # CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
@@ -1104,97 +1058,30 @@ CONFIG_SOUND=y
 #
 # Advanced Linux Sound Architecture
 #
-CONFIG_SND=y
-CONFIG_SND_TIMER=y
-CONFIG_SND_PCM=y
-CONFIG_SND_RAWMIDI=y
-CONFIG_SND_SEQUENCER=y
-# CONFIG_SND_SEQ_DUMMY is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
-# CONFIG_SND_SEQUENCER_OSS is not set
-CONFIG_SND_RTCTIMER=y
-CONFIG_SND_SEQ_RTCTIMER_DEFAULT=y
-# CONFIG_SND_DYNAMIC_MINORS is not set
-# CONFIG_SND_SUPPORT_OLD_API is not set
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-
-#
-# Generic devices
-#
-CONFIG_SND_MPU401_UART=y
-CONFIG_SND_AC97_CODEC=y
-CONFIG_SND_AC97_BUS=y
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_VIRMIDI is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-
-#
-# PCI devices
-#
-# CONFIG_SND_AD1889 is not set
-# CONFIG_SND_ALS4000 is not set
-# CONFIG_SND_ALI5451 is not set
-# CONFIG_SND_ATIIXP is not set
-# CONFIG_SND_ATIIXP_MODEM is not set
-# CONFIG_SND_AU8810 is not set
-# CONFIG_SND_AU8820 is not set
-# CONFIG_SND_AU8830 is not set
-# CONFIG_SND_AZT3328 is not set
-# CONFIG_SND_BT87X is not set
-# CONFIG_SND_CA0106 is not set
-# CONFIG_SND_CMIPCI is not set
-# CONFIG_SND_CS4281 is not set
-# CONFIG_SND_CS46XX is not set
-# CONFIG_SND_CS5535AUDIO is not set
-# CONFIG_SND_EMU10K1 is not set
-# CONFIG_SND_EMU10K1X is not set
-# CONFIG_SND_ENS1370 is not set
-# CONFIG_SND_ENS1371 is not set
-# CONFIG_SND_ES1938 is not set
-# CONFIG_SND_ES1968 is not set
-# CONFIG_SND_FM801 is not set
-# CONFIG_SND_HDA_INTEL is not set
-# CONFIG_SND_HDSP is not set
-# CONFIG_SND_HDSPM is not set
-# CONFIG_SND_ICE1712 is not set
-# CONFIG_SND_ICE1724 is not set
-# CONFIG_SND_INTEL8X0 is not set
-# CONFIG_SND_INTEL8X0M is not set
-# CONFIG_SND_KORG1212 is not set
-# CONFIG_SND_MAESTRO3 is not set
-# CONFIG_SND_MIXART is not set
-# CONFIG_SND_NM256 is not set
-# CONFIG_SND_PCXHR is not set
-# CONFIG_SND_RME32 is not set
-# CONFIG_SND_RME96 is not set
-# CONFIG_SND_RME9652 is not set
-# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_TRIDENT is not set
-CONFIG_SND_VIA82XX=y
-# CONFIG_SND_VIA82XX_MODEM is not set
-# CONFIG_SND_VX222 is not set
-# CONFIG_SND_YMFPCI is not set
-
-#
-# USB devices
-#
-# CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_USX2Y is not set
+# CONFIG_SND is not set
 
 #
 # Open Sound System
 #
-# CONFIG_SOUND_PRIME is not set
+CONFIG_SOUND_PRIME=y
+CONFIG_OSS_OBSOLETE_DRIVER=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_ES1371 is not set
+CONFIG_SOUND_ICH=y
+# 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_SOUND_OSS is not set
 
 #
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -1213,17 +1100,19 @@ CONFIG_USB_DEVICEFS=y
 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_ISP116X_HCD is not set
-# CONFIG_USB_OHCI_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_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
 
 #
 # USB Device Class drivers
 #
-# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
 # CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
+CONFIG_USB_PRINTER=y
 
 #
 # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
@@ -1248,21 +1137,17 @@ CONFIG_USB_STORAGE=y
 #
 # 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_HID=y
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV 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_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX 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
@@ -1276,21 +1161,6 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
 
-#
-# USB Multimedia devices
-#
-# CONFIG_USB_DABUSB is not set
-# CONFIG_USB_VICAM is not set
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_ET61X251 is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_KONICAWC is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_SE401 is not set
-# CONFIG_USB_SN9C102 is not set
-# CONFIG_USB_STV680 is not set
-# CONFIG_USB_PWC is not set
-
 #
 # USB Network Adapters
 #
@@ -1299,12 +1169,11 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
-# CONFIG_USB_MON is not set
+CONFIG_USB_MON=y
 
 #
 # USB port drivers
 #
-# CONFIG_USB_USS720 is not set
 
 #
 # USB Serial Converter support
@@ -1321,10 +1190,12 @@ CONFIG_USB_STORAGE=y
 # 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_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
 # CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_APPLEDISPLAY is not set
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TEST is not set
@@ -1343,57 +1214,97 @@ CONFIG_USB_STORAGE=y
 #
 # CONFIG_MMC is not set
 
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
 #
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
 
 #
-# SN Devices
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+# CONFIG_EDAC is not set
+
+#
+# Real Time Clock
 #
+# CONFIG_RTC_CLASS is not set
 
 #
-# EDAC - error detection and reporting (RAS)
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
 #
-# CONFIG_EDAC is not set
 
 #
 # File systems
 #
 CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_EXT2_FS_SECURITY is not set
 # CONFIG_EXT2_FS_XIP is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_REISERFS_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+# CONFIG_REISERFS_FS_SECURITY is not set
 # CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FS_POSIX_ACL=y
 # CONFIG_XFS_FS is not set
 # CONFIG_OCFS2_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
-# CONFIG_INOTIFY 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_AUTOFS4_FS=y
 # CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-CONFIG_ZISOFS=y
-CONFIG_ZISOFS_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
 # CONFIG_UDF_FS is not set
 
 #
 # DOS/FAT/NT Filesystems
 #
 CONFIG_FAT_FS=y
-# CONFIG_MSDOS_FS is not set
+CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=850
+CONFIG_FAT_DEFAULT_CODEPAGE=437
 CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
@@ -1404,10 +1315,9 @@ CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
-# CONFIG_RELAYFS_FS is not set
 # CONFIG_CONFIGFS_FS is not set
 
 #
@@ -1430,13 +1340,26 @@ CONFIG_RAMFS=y
 #
 # Network File Systems
 #
-# CONFIG_NFS_FS is not set
-# CONFIG_NFSD is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=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=y
-# CONFIG_CIFS_STATS is not set
-# CONFIG_CIFS_XATTR is not set
-# CONFIG_CIFS_EXPERIMENTAL 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
@@ -1445,33 +1368,18 @@ CONFIG_CIFS=y
 #
 # Partition Types
 #
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
+# CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
 
 #
 # Native Language Support
 #
 CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-15"
-# CONFIG_NLS_CODEPAGE_437 is not set
+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_850 is not set
 # CONFIG_NLS_CODEPAGE_852 is not set
 # CONFIG_NLS_CODEPAGE_855 is not set
 # CONFIG_NLS_CODEPAGE_857 is not set
@@ -1491,7 +1399,7 @@ CONFIG_NLS_CODEPAGE_850=y
 # 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_ASCII=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -1510,20 +1418,50 @@ CONFIG_NLS_UTF8=y
 #
 # Instrumentation Support
 #
-# CONFIG_PROFILING is not set
-# CONFIG_KPROBES is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
 
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_UNUSED_SYMBOLS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_LOG_BUF_SHIFT=18
+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_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING 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_HIGHMEM is not set
 CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_FRAME_POINTER is not set
+CONFIG_UNWIND_INFO=y
+CONFIG_STACK_UNWIND=y
+# CONFIG_FORCED_INLINING is not set
+# CONFIG_RCU_TORTURE_TEST is not set
 CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_RODATA is not set
+# CONFIG_4KSTACKS is not set
 CONFIG_X86_FIND_SMP_CONFIG=y
 CONFIG_X86_MPPARSE=y
+CONFIG_DOUBLEFAULT=y
 
 #
 # Security options
@@ -1536,10 +1474,6 @@ CONFIG_X86_MPPARSE=y
 #
 # CONFIG_CRYPTO is not set
 
-#
-# Hardware crypto devices
-#
-
 #
 # Library routines
 #
@@ -1548,7 +1482,12 @@ CONFIG_X86_MPPARSE=y
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
+CONFIG_PLIST=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_X86_SMP=y
+CONFIG_X86_HT=y
 CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
 CONFIG_KTIME_SCALAR=y
index 5427a842e841d90ee09e77628cce1abb3d402ea8..1a884b6e6e5c97d472fb5c0e8c10d982f806d2f9 100644 (file)
@@ -4,7 +4,7 @@
 
 extra-y := head.o init_task.o vmlinux.lds
 
-obj-y  := process.o semaphore.o signal.o entry.o traps.o irq.o \
+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_i386.o \
                pci-dma.o i386_ksyms.o i387.o bootflag.o \
                quirks.o i8237.o topology.o alternative.o i8253.o tsc.o
@@ -81,4 +81,5 @@ $(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
        $(call if_changed,syscall)
 
 k8-y                      += ../../x86_64/kernel/k8.o
+stacktrace-y             += ../../x86_64/kernel/stacktrace.o
 
index 7e9ac99354f43212bbbb6aa959642b0ec7dce91c..7f7be01f44e66cd27257870d540ed38d3f1e1661 100644 (file)
@@ -1,5 +1,7 @@
 obj-$(CONFIG_ACPI)             += boot.o
+ifneq ($(CONFIG_PCI),)
 obj-$(CONFIG_X86_IO_APIC)      += earlyquirk.o
+endif
 obj-$(CONFIG_ACPI_SLEEP)       += sleep.o wakeup.o
 
 ifneq ($(CONFIG_ACPI_PROCESSOR),)
index ee003bc0e8b114ba754b4fc5f6ce70da0b206338..1aaea6ab8c463dec58d53c3a861d44a909fbc9e4 100644 (file)
 #include <linux/init.h>
 #include <linux/acpi.h>
 #include <linux/efi.h>
+#include <linux/cpumask.h>
 #include <linux/module.h>
 #include <linux/dmi.h>
 #include <linux/irq.h>
+#include <linux/bootmem.h>
+#include <linux/ioport.h>
 
 #include <asm/pgtable.h>
 #include <asm/io_apic.h>
 #include <asm/io.h>
 #include <asm/mpspec.h>
 
-#ifdef CONFIG_X86_64
+static int __initdata acpi_force = 0;
 
-extern void __init clustered_apic_check(void);
+#ifdef CONFIG_ACPI
+int acpi_disabled = 0;
+#else
+int acpi_disabled = 1;
+#endif
+EXPORT_SYMBOL(acpi_disabled);
+
+#ifdef CONFIG_X86_64
 
-extern int gsi_irq_sharing(int gsi);
 #include <asm/proto.h>
 
 static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { return 0; }
@@ -506,16 +515,76 @@ EXPORT_SYMBOL(acpi_register_gsi);
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
 int acpi_map_lsapic(acpi_handle handle, int *pcpu)
 {
-       /* TBD */
-       return -EINVAL;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *obj;
+       struct acpi_table_lapic *lapic;
+       cpumask_t tmp_map, new_map;
+       u8 physid;
+       int cpu;
+
+       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
+               return -EINVAL;
+
+       if (!buffer.length || !buffer.pointer)
+               return -EINVAL;
+
+       obj = buffer.pointer;
+       if (obj->type != ACPI_TYPE_BUFFER ||
+           obj->buffer.length < sizeof(*lapic)) {
+               kfree(buffer.pointer);
+               return -EINVAL;
+       }
+
+       lapic = (struct acpi_table_lapic *)obj->buffer.pointer;
+
+       if ((lapic->header.type != ACPI_MADT_LAPIC) ||
+           (!lapic->flags.enabled)) {
+               kfree(buffer.pointer);
+               return -EINVAL;
+       }
+
+       physid = lapic->id;
+
+       kfree(buffer.pointer);
+       buffer.length = ACPI_ALLOCATE_BUFFER;
+       buffer.pointer = NULL;
+
+       tmp_map = cpu_present_map;
+       mp_register_lapic(physid, lapic->flags.enabled);
+
+       /*
+        * If mp_register_lapic successfully generates a new logical cpu
+        * number, then the following will get us exactly what was mapped
+        */
+       cpus_andnot(new_map, cpu_present_map, tmp_map);
+       if (cpus_empty(new_map)) {
+               printk ("Unable to map lapic to logical cpu number\n");
+               return -EINVAL;
+       }
+
+       cpu = first_cpu(new_map);
+
+       *pcpu = cpu;
+       return 0;
 }
 
 EXPORT_SYMBOL(acpi_map_lsapic);
 
 int acpi_unmap_lsapic(int cpu)
 {
-       /* TBD */
-       return -EINVAL;
+       int i;
+
+       for_each_possible_cpu(i) {
+               if (x86_acpiid_to_apicid[i] == x86_cpu_to_apicid[cpu]) {
+                       x86_acpiid_to_apicid[i] = -1;
+                       break;
+               }
+       }
+       x86_cpu_to_apicid[cpu] = -1;
+       cpu_clear(cpu, cpu_present_map);
+       num_processors--;
+
+       return (0);
 }
 
 EXPORT_SYMBOL(acpi_unmap_lsapic);
@@ -579,6 +648,8 @@ static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size)
 static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
 {
        struct acpi_table_hpet *hpet_tbl;
+       struct resource *hpet_res;
+       resource_size_t res_start;
 
        if (!phys || !size)
                return -EINVAL;
@@ -594,12 +665,26 @@ static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
                       "memory.\n");
                return -1;
        }
+
+#define HPET_RESOURCE_NAME_SIZE 9
+       hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE);
+       if (hpet_res) {
+               memset(hpet_res, 0, sizeof(*hpet_res));
+               hpet_res->name = (void *)&hpet_res[1];
+               hpet_res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE,
+                        "HPET %u", hpet_tbl->number);
+               hpet_res->end = (1 * 1024) - 1;
+       }
+
 #ifdef CONFIG_X86_64
        vxtime.hpet_address = hpet_tbl->addr.addrl |
            ((long)hpet_tbl->addr.addrh << 32);
 
        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;
@@ -607,9 +692,17 @@ static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
                hpet_address = hpet_tbl->addr.addrl;
                printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
                       hpet_tbl->id, hpet_address);
+
+               res_start = hpet_address;
        }
 #endif                         /* X86 */
 
+       if (hpet_res) {
+               hpet_res->start = res_start;
+               hpet_res->end += res_start;
+               insert_resource(&iomem_resource, hpet_res);
+       }
+
        return 0;
 }
 #else
@@ -860,8 +953,6 @@ static void __init acpi_process_madt(void)
        return;
 }
 
-extern int acpi_force;
-
 #ifdef __i386__
 
 static int __init disable_acpi_irq(struct dmi_system_id *d)
@@ -1163,3 +1254,75 @@ int __init acpi_boot_init(void)
 
        return 0;
 }
+
+static int __init parse_acpi(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
+
+       /* "acpi=off" disables both ACPI table parsing and interpreter */
+       if (strcmp(arg, "off") == 0) {
+               disable_acpi();
+       }
+       /* acpi=force to over-ride black-list */
+       else if (strcmp(arg, "force") == 0) {
+               acpi_force = 1;
+               acpi_ht = 1;
+               acpi_disabled = 0;
+       }
+       /* acpi=strict disables out-of-spec workarounds */
+       else if (strcmp(arg, "strict") == 0) {
+               acpi_strict = 1;
+       }
+       /* Limit ACPI just to boot-time to enable HT */
+       else if (strcmp(arg, "ht") == 0) {
+               if (!acpi_force)
+                       disable_acpi();
+               acpi_ht = 1;
+       }
+       /* "acpi=noirq" disables ACPI interrupt routing */
+       else if (strcmp(arg, "noirq") == 0) {
+               acpi_noirq_set();
+       } else {
+               /* Core will printk when we return error. */
+               return -EINVAL;
+       }
+       return 0;
+}
+early_param("acpi", parse_acpi);
+
+/* FIXME: Using pci= for an ACPI parameter is a travesty. */
+static int __init parse_pci(char *arg)
+{
+       if (arg && strcmp(arg, "noacpi") == 0)
+               acpi_disable_pci();
+       return 0;
+}
+early_param("pci", parse_pci);
+
+#ifdef CONFIG_X86_IO_APIC
+static int __init parse_acpi_skip_timer_override(char *arg)
+{
+       acpi_skip_timer_override = 1;
+       return 0;
+}
+early_param("acpi_skip_timer_override", parse_acpi_skip_timer_override);
+#endif /* CONFIG_X86_IO_APIC */
+
+static int __init setup_acpi_sci(char *s)
+{
+       if (!s)
+               return -EINVAL;
+       if (!strcmp(s, "edge"))
+               acpi_sci_flags.trigger = 1;
+       else if (!strcmp(s, "level"))
+               acpi_sci_flags.trigger = 3;
+       else if (!strcmp(s, "high"))
+               acpi_sci_flags.polarity = 1;
+       else if (!strcmp(s, "low"))
+               acpi_sci_flags.polarity = 3;
+       else
+               return -EINVAL;
+       return 0;
+}
+early_param("acpi_sci", setup_acpi_sci);
index 1649a175a206ab4bd6ed0add0040580ff83d036e..fe799b11ac0a7e9ce0b6707fe561902a4b4ad4ab 100644 (file)
@@ -48,7 +48,11 @@ void __init check_acpi_pci(void)
        int num, slot, func;
 
        /* Assume the machine supports type 1. If not it will 
-          always read ffffffff and should not have any side effect. */
+          always read ffffffff and should not have any side effect.
+          Actually a few buggy systems can machine check. Allow the user
+          to disable it by command line option at least -AK */
+       if (!early_pci_allowed())
+               return;
 
        /* Poor man's PCI discovery */
        for (num = 0; num < 32; num++) {
index 8c844d07862f6f9eb9103842f783a0cdf495cda3..90faae5c5d30a5451ce1e70e743eaca62424598c 100644 (file)
@@ -52,7 +52,18 @@ static cpumask_t timer_bcast_ipi;
 /*
  * Knob to control our willingness to enable the local APIC.
  */
-int enable_local_apic __initdata = 0; /* -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 inline void lapic_enable(void)
+{
+       enable_local_apic = 1;
+}
 
 /*
  * Debug level
@@ -586,8 +597,7 @@ void __devinit setup_local_APIC(void)
                        printk("No ESR for 82489DX.\n");
        }
 
-       if (nmi_watchdog == NMI_LOCAL_APIC)
-               setup_apic_nmi_watchdog();
+       setup_apic_nmi_watchdog(NULL);
        apic_pm_activate();
 }
 
@@ -1373,3 +1383,18 @@ int __init APIC_init_uniprocessor (void)
 
        return 0;
 }
+
+static int __init parse_lapic(char *arg)
+{
+       lapic_enable();
+       return 0;
+}
+early_param("lapic", parse_lapic);
+
+static int __init parse_nolapic(char *arg)
+{
+       lapic_disable();
+       return 0;
+}
+early_param("nolapic", parse_nolapic);
+
index e6a2d6b80cdae8a84e72566da1642bff59a7dc7a..e4758095d87a8d72232f3876a2973adcd06db92a 100644 (file)
@@ -22,7 +22,7 @@
 extern void vide(void);
 __asm__(".align 4\nvide: ret");
 
-static void __init init_amd(struct cpuinfo_x86 *c)
+static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 {
        u32 l, h;
        int mbytes = num_physpages >> (20-PAGE_SHIFT);
@@ -246,7 +246,7 @@ static void __init init_amd(struct cpuinfo_x86 *c)
                num_cache_leaves = 3;
 }
 
-static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
+static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
 {
        /* AMD errata T13 (order #21922) */
        if ((c->x86 == 6)) {
@@ -259,7 +259,7 @@ static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
        return size;
 }
 
-static struct cpu_dev amd_cpu_dev __initdata = {
+static struct cpu_dev amd_cpu_dev __cpuinitdata = {
        .c_vendor       = "AMD",
        .c_ident        = { "AuthenticAMD" },
        .c_models = {
@@ -275,7 +275,6 @@ static struct cpu_dev amd_cpu_dev __initdata = {
                },
        },
        .c_init         = init_amd,
-       .c_identify     = generic_identify,
        .c_size_cache   = amd_size_cache,
 };
 
index bd75629dd262b319d975567cc426b727e447eaaa..8c25047975c0615a0f503b810f9c2605f025d466 100644 (file)
@@ -9,7 +9,7 @@
 
 #ifdef CONFIG_X86_OOSTORE
 
-static u32 __init power2(u32 x)
+static u32 __cpuinit power2(u32 x)
 {
        u32 s=1;
        while(s<=x)
@@ -22,7 +22,7 @@ static u32 __init power2(u32 x)
  *     Set up an actual MCR
  */
  
-static void __init centaur_mcr_insert(int reg, u32 base, u32 size, int key)
+static void __cpuinit centaur_mcr_insert(int reg, u32 base, u32 size, int key)
 {
        u32 lo, hi;
        
@@ -40,7 +40,7 @@ static void __init centaur_mcr_insert(int reg, u32 base, u32 size, int key)
  *     Shortcut: We know you can't put 4Gig of RAM on a winchip
  */
 
-static u32 __init ramtop(void)         /* 16388 */
+static u32 __cpuinit ramtop(void)              /* 16388 */
 {
        int i;
        u32 top = 0;
@@ -91,7 +91,7 @@ static u32 __init ramtop(void)                /* 16388 */
  *     Compute a set of MCR's to give maximum coverage
  */
 
-static int __init centaur_mcr_compute(int nr, int key)
+static int __cpuinit centaur_mcr_compute(int nr, int key)
 {
        u32 mem = ramtop();
        u32 root = power2(mem);
@@ -166,7 +166,7 @@ static int __init centaur_mcr_compute(int nr, int key)
        return ct;
 }
 
-static void __init centaur_create_optimal_mcr(void)
+static void __cpuinit centaur_create_optimal_mcr(void)
 {
        int i;
        /*
@@ -189,7 +189,7 @@ static void __init centaur_create_optimal_mcr(void)
                wrmsr(MSR_IDT_MCR0+i, 0, 0);
 }
 
-static void __init winchip2_create_optimal_mcr(void)
+static void __cpuinit winchip2_create_optimal_mcr(void)
 {
        u32 lo, hi;
        int i;
@@ -227,7 +227,7 @@ static void __init winchip2_create_optimal_mcr(void)
  *     Handle the MCR key on the Winchip 2.
  */
 
-static void __init winchip2_unprotect_mcr(void)
+static void __cpuinit winchip2_unprotect_mcr(void)
 {
        u32 lo, hi;
        u32 key;
@@ -239,7 +239,7 @@ static void __init winchip2_unprotect_mcr(void)
        wrmsr(MSR_IDT_MCR_CTRL, lo, hi);
 }
 
-static void __init winchip2_protect_mcr(void)
+static void __cpuinit winchip2_protect_mcr(void)
 {
        u32 lo, hi;
        
@@ -257,7 +257,7 @@ static void __init winchip2_protect_mcr(void)
 #define RNG_ENABLED    (1 << 3)
 #define RNG_ENABLE     (1 << 6)        /* MSR_VIA_RNG */
 
-static void __init init_c3(struct cpuinfo_x86 *c)
+static void __cpuinit init_c3(struct cpuinfo_x86 *c)
 {
        u32  lo, hi;
 
@@ -303,7 +303,7 @@ static void __init init_c3(struct cpuinfo_x86 *c)
        display_cacheinfo(c);
 }
 
-static void __init init_centaur(struct cpuinfo_x86 *c)
+static void __cpuinit init_centaur(struct cpuinfo_x86 *c)
 {
        enum {
                ECX8=1<<1,
@@ -442,7 +442,7 @@ static void __init init_centaur(struct cpuinfo_x86 *c)
        }
 }
 
-static unsigned int centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size)
+static unsigned int __cpuinit centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size)
 {
        /* VIA C3 CPUs (670-68F) need further shifting. */
        if ((c->x86 == 6) && ((c->x86_model == 7) || (c->x86_model == 8)))
@@ -457,7 +457,7 @@ static unsigned int centaur_size_cache(struct cpuinfo_x86 * c, unsigned int size
        return size;
 }
 
-static struct cpu_dev centaur_cpu_dev __initdata = {
+static struct cpu_dev centaur_cpu_dev __cpuinitdata = {
        .c_vendor       = "Centaur",
        .c_ident        = { "CentaurHauls" },
        .c_init         = init_centaur,
index 70c87de582c7a793ab346b60c4416bcdaa3a9f2c..2799baaadf45f5b7afbabbbc588a438d5308b190 100644 (file)
@@ -36,7 +36,7 @@ struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
 
 extern int disable_pse;
 
-static void default_init(struct cpuinfo_x86 * c)
+static void __cpuinit default_init(struct cpuinfo_x86 * c)
 {
        /* Not much we can do here... */
        /* Check if at least it has cpuid */
@@ -49,7 +49,7 @@ static void default_init(struct cpuinfo_x86 * c)
        }
 }
 
-static struct cpu_dev default_cpu = {
+static struct cpu_dev __cpuinitdata default_cpu = {
        .c_init = default_init,
        .c_vendor = "Unknown",
 };
@@ -265,7 +265,7 @@ static void __init early_cpu_detect(void)
        }
 }
 
-void __cpuinit generic_identify(struct cpuinfo_x86 * c)
+static void __cpuinit generic_identify(struct cpuinfo_x86 * c)
 {
        u32 tfms, xlvl;
        int ebx;
@@ -675,7 +675,7 @@ old_gdt:
 #endif
 
        /* Clear %fs and %gs. */
-       asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
+       asm volatile ("movl %0, %%fs; movl %0, %%gs" : : "r" (0));
 
        /* Clear all 6 debug registers: */
        set_debugreg(0, 0);
index 5a1d4f163e84d6ff75a28aa91c6c65e3b53a717a..2f6432cef6ffb68c4bd9391f34313d20ca66cdb1 100644 (file)
@@ -24,7 +24,5 @@ extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM];
 extern int get_model_name(struct cpuinfo_x86 *c);
 extern void display_cacheinfo(struct cpuinfo_x86 *c);
 
-extern void generic_identify(struct cpuinfo_x86 * c);
-
 extern void early_intel_workaround(struct cpuinfo_x86 *c);
 
index f03b7f94c304af1cc742745d439fb4b72eae1e6e..c0c3b59de32c4d183b677e843ffacffa5aa2f1bb 100644 (file)
@@ -12,7 +12,7 @@
 /*
  * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU
  */
-static void __init do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
+static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
 {
        unsigned char ccr2, ccr3;
        unsigned long flags;
@@ -52,25 +52,25 @@ static void __init do_cyrix_devid(unsigned char *dir0, unsigned char *dir1)
  * Actually since bugs.h doesn't even reference this perhaps someone should
  * fix the documentation ???
  */
-static unsigned char Cx86_dir0_msb __initdata = 0;
+static unsigned char Cx86_dir0_msb __cpuinitdata = 0;
 
-static char Cx86_model[][9] __initdata = {
+static char Cx86_model[][9] __cpuinitdata = {
        "Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ",
        "M II ", "Unknown"
 };
-static char Cx486_name[][5] __initdata = {
+static char Cx486_name[][5] __cpuinitdata = {
        "SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx",
        "SRx2", "DRx2"
 };
-static char Cx486S_name[][4] __initdata = {
+static char Cx486S_name[][4] __cpuinitdata = {
        "S", "S2", "Se", "S2e"
 };
-static char Cx486D_name[][4] __initdata = {
+static char Cx486D_name[][4] __cpuinitdata = {
        "DX", "DX2", "?", "?", "?", "DX4"
 };
-static char Cx86_cb[] __initdata = "?.5x Core/Bus Clock";
-static char cyrix_model_mult1[] __initdata = "12??43";
-static char cyrix_model_mult2[] __initdata = "12233445";
+static char Cx86_cb[] __cpuinitdata = "?.5x Core/Bus Clock";
+static char cyrix_model_mult1[] __cpuinitdata = "12??43";
+static char cyrix_model_mult2[] __cpuinitdata = "12233445";
 
 /*
  * Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old
@@ -82,7 +82,7 @@ static char cyrix_model_mult2[] __initdata = "12233445";
 
 extern void calibrate_delay(void) __init;
 
-static void __init check_cx686_slop(struct cpuinfo_x86 *c)
+static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c)
 {
        unsigned long flags;
        
@@ -107,7 +107,7 @@ static void __init check_cx686_slop(struct cpuinfo_x86 *c)
 }
 
 
-static void __init set_cx86_reorder(void)
+static void __cpuinit set_cx86_reorder(void)
 {
        u8 ccr3;
 
@@ -122,7 +122,7 @@ static void __init set_cx86_reorder(void)
        setCx86(CX86_CCR3, ccr3);
 }
 
-static void __init set_cx86_memwb(void)
+static void __cpuinit set_cx86_memwb(void)
 {
        u32 cr0;
 
@@ -137,7 +137,7 @@ static void __init set_cx86_memwb(void)
        setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
 }
 
-static void __init set_cx86_inc(void)
+static void __cpuinit set_cx86_inc(void)
 {
        unsigned char ccr3;
 
@@ -158,7 +158,7 @@ static void __init set_cx86_inc(void)
  *     Configure later MediaGX and/or Geode processor.
  */
 
-static void __init geode_configure(void)
+static void __cpuinit geode_configure(void)
 {
        unsigned long flags;
        u8 ccr3, ccr4;
@@ -184,14 +184,14 @@ static void __init geode_configure(void)
 
 
 #ifdef CONFIG_PCI
-static struct pci_device_id __initdata cyrix_55x0[] = {
+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 __init init_cyrix(struct cpuinfo_x86 *c)
+static void __cpuinit init_cyrix(struct cpuinfo_x86 *c)
 {
        unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0;
        char *buf = c->x86_model_id;
@@ -346,7 +346,7 @@ static void __init init_cyrix(struct cpuinfo_x86 *c)
 /*
  * Handle National Semiconductor branded processors
  */
-static void __init init_nsc(struct cpuinfo_x86 *c)
+static void __cpuinit init_nsc(struct cpuinfo_x86 *c)
 {
        /* There may be GX1 processors in the wild that are branded
         * NSC and not Cyrix.
@@ -394,7 +394,7 @@ static inline int test_cyrix_52div(void)
        return (unsigned char) (test >> 8) == 0x02;
 }
 
-static void cyrix_identify(struct cpuinfo_x86 * c)
+static void __cpuinit cyrix_identify(struct cpuinfo_x86 * c)
 {
        /* Detect Cyrix with disabled CPUID */
        if ( c->x86 == 4 && test_cyrix_52div() ) {
@@ -427,10 +427,9 @@ static void cyrix_identify(struct cpuinfo_x86 * c)
                        local_irq_restore(flags);
                }
        }
-       generic_identify(c);
 }
 
-static struct cpu_dev cyrix_cpu_dev __initdata = {
+static struct cpu_dev cyrix_cpu_dev __cpuinitdata = {
        .c_vendor       = "Cyrix",
        .c_ident        = { "CyrixInstead" },
        .c_init         = init_cyrix,
@@ -453,11 +452,10 @@ static int __init cyrix_exit_cpu(void)
 
 late_initcall(cyrix_exit_cpu);
 
-static struct cpu_dev nsc_cpu_dev __initdata = {
+static struct cpu_dev nsc_cpu_dev __cpuinitdata = {
        .c_vendor       = "NSC",
        .c_ident        = { "Geode by NSC" },
        .c_init         = init_nsc,
-       .c_identify     = generic_identify,
 };
 
 int __init nsc_init_cpu(void)
index 5a2e270924b13727f1411eb11dea7a0f114e7cce..94a95aa5227e8be03735f56a6ecd5c84638e2be7 100644 (file)
@@ -198,7 +198,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 }
 
 
-static unsigned int intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
+static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
 {
        /* Intel PIII Tualatin. This comes in two flavours.
         * One has 256kb of cache, the other 512. We have no way
@@ -263,7 +263,6 @@ static struct cpu_dev intel_cpu_dev __cpuinitdata = {
                },
        },
        .c_init         = init_intel,
-       .c_identify     = generic_identify,
        .c_size_cache   = intel_size_cache,
 };
 
index 30808f3d6715f3abf0246cec66b29b39ab6e733f..f1ebe1c1c17afd29229d30efdee30d4055f70021 100644 (file)
@@ -1,2 +1,2 @@
-obj-y  =       mce.o k7.o p4.o p5.o p6.o winchip.o
+obj-y  =       mce.o k7.o p4.o p5.o p6.o winchip.o therm_throt.o
 obj-$(CONFIG_X86_MCE_NONFATAL) +=      non-fatal.o
index b95f1b3d53aa1c20761491f280abe819dbe3eb17..504434a46011e2ca553a7e6f67ccfad3c5ec7fc1 100644 (file)
@@ -13,6 +13,8 @@
 #include <asm/msr.h>
 #include <asm/apic.h>
 
+#include <asm/therm_throt.h>
+
 #include "mce.h"
 
 /* as supported by the P4/Xeon family */
@@ -44,25 +46,12 @@ static void unexpected_thermal_interrupt(struct pt_regs *regs)
 /* P4/Xeon Thermal transition interrupt handler */
 static void intel_thermal_interrupt(struct pt_regs *regs)
 {
-       u32 l, h;
-       unsigned int cpu = smp_processor_id();
-       static unsigned long next[NR_CPUS];
+       __u64 msr_val;
 
        ack_APIC_irq();
 
-       if (time_after(next[cpu], jiffies))
-               return;
-
-       next[cpu] = jiffies + HZ*5;
-       rdmsr(MSR_IA32_THERM_STATUS, l, h);
-       if (l & 0x1) {
-               printk(KERN_EMERG "CPU%d: Temperature above threshold\n", cpu);
-               printk(KERN_EMERG "CPU%d: Running in modulated clock mode\n",
-                               cpu);
-               add_taint(TAINT_MACHINE_CHECK);
-       } else {
-               printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu);
-       }
+       rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
+       therm_throt_process(msr_val & 0x1);
 }
 
 /* Thermal interrupt handler for this CPU setup */
@@ -122,10 +111,13 @@ static void intel_init_thermal(struct cpuinfo_x86 *c)
        
        rdmsr (MSR_IA32_MISC_ENABLE, l, h);
        wrmsr (MSR_IA32_MISC_ENABLE, l | (1<<3), h);
-       
+
        l = apic_read (APIC_LVTTHMR);
        apic_write_around (APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
        printk (KERN_INFO "CPU%d: Thermal monitoring enabled\n", cpu);
+
+       /* enable thermal throttle processing */
+       atomic_set(&therm_throt_en, 1);
        return;
 }
 #endif /* CONFIG_X86_MCE_P4THERMAL */
diff --git a/arch/i386/kernel/cpu/mcheck/therm_throt.c b/arch/i386/kernel/cpu/mcheck/therm_throt.c
new file mode 100644 (file)
index 0000000..4f43047
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * linux/arch/i386/kerne/cpu/mcheck/therm_throt.c
+ *
+ * Thermal throttle event support code (such as syslog messaging and rate
+ * limiting) that was factored out from x86_64 (mce_intel.c) and i386 (p4.c).
+ * This allows consistent reporting of CPU thermal throttle events.
+ *
+ * Maintains a counter in /sys that keeps track of the number of thermal
+ * events, such that the user knows how bad the thermal problem might be
+ * (since the logging to syslog and mcelog is rate limited).
+ *
+ * Author: Dmitriy Zavin (dmitriyz@google.com)
+ *
+ * Credits: Adapted from Zwane Mwaikambo's original code in mce_intel.c.
+ *          Inspired by Ross Biro's and Al Borchers' counter code.
+ */
+
+#include <linux/percpu.h>
+#include <linux/sysdev.h>
+#include <linux/cpu.h>
+#include <asm/cpu.h>
+#include <linux/notifier.h>
+#include <asm/therm_throt.h>
+
+/* How long to wait between reporting thermal events */
+#define CHECK_INTERVAL              (300 * HZ)
+
+static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES;
+static DEFINE_PER_CPU(unsigned long, thermal_throttle_count);
+atomic_t therm_throt_en = ATOMIC_INIT(0);
+
+#ifdef CONFIG_SYSFS
+#define define_therm_throt_sysdev_one_ro(_name)                              \
+        static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL)
+
+#define define_therm_throt_sysdev_show_func(name)                            \
+static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev,        \
+                                              char *buf)                     \
+{                                                                            \
+       unsigned int cpu = dev->id;                                          \
+       ssize_t ret;                                                         \
+                                                                             \
+       preempt_disable();              /* CPU hotplug */                    \
+       if (cpu_online(cpu))                                                 \
+               ret = sprintf(buf, "%lu\n",                                  \
+                             per_cpu(thermal_throttle_##name, cpu));        \
+       else                                                                 \
+               ret = 0;                                                     \
+       preempt_enable();                                                    \
+                                                                             \
+       return ret;                                                          \
+}
+
+define_therm_throt_sysdev_show_func(count);
+define_therm_throt_sysdev_one_ro(count);
+
+static struct attribute *thermal_throttle_attrs[] = {
+       &attr_count.attr,
+       NULL
+};
+
+static struct attribute_group thermal_throttle_attr_group = {
+       .attrs = thermal_throttle_attrs,
+       .name = "thermal_throttle"
+};
+#endif /* CONFIG_SYSFS */
+
+/***
+ * therm_throt_process - Process thermal throttling event from interrupt
+ * @curr: Whether the condition is current or not (boolean), since the
+ *        thermal interrupt normally gets called both when the thermal
+ *        event begins and once the event has ended.
+ *
+ * This function is called by the thermal interrupt after the
+ * IRQ has been acknowledged.
+ *
+ * It will take care of rate limiting and printing messages to the syslog.
+ *
+ * Returns: 0 : Event should NOT be further logged, i.e. still in
+ *              "timeout" from previous log message.
+ *          1 : Event should be logged further, and a message has been
+ *              printed to the syslog.
+ */
+int therm_throt_process(int curr)
+{
+       unsigned int cpu = smp_processor_id();
+       __u64 tmp_jiffs = get_jiffies_64();
+
+       if (curr)
+               __get_cpu_var(thermal_throttle_count)++;
+
+       if (time_before64(tmp_jiffs, __get_cpu_var(next_check)))
+               return 0;
+
+       __get_cpu_var(next_check) = tmp_jiffs + CHECK_INTERVAL;
+
+       /* if we just entered the thermal event */
+       if (curr) {
+               printk(KERN_CRIT "CPU%d: Temperature above threshold, "
+                      "cpu clock throttled (total events = %lu)\n", cpu,
+                      __get_cpu_var(thermal_throttle_count));
+
+               add_taint(TAINT_MACHINE_CHECK);
+       } else {
+               printk(KERN_CRIT "CPU%d: Temperature/speed normal\n", cpu);
+       }
+
+       return 1;
+}
+
+#ifdef CONFIG_SYSFS
+/* Add/Remove thermal_throttle interface for CPU device */
+static __cpuinit int thermal_throttle_add_dev(struct sys_device * sys_dev)
+{
+       sysfs_create_group(&sys_dev->kobj, &thermal_throttle_attr_group);
+       return 0;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static __cpuinit int thermal_throttle_remove_dev(struct sys_device * sys_dev)
+{
+       sysfs_remove_group(&sys_dev->kobj, &thermal_throttle_attr_group);
+       return 0;
+}
+
+/* Mutex protecting device creation against CPU hotplug */
+static DEFINE_MUTEX(therm_cpu_lock);
+
+/* Get notified when a cpu comes on/off. Be hotplug friendly. */
+static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb,
+                                                  unsigned long action,
+                                                  void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+       struct sys_device *sys_dev;
+
+       sys_dev = get_cpu_sysdev(cpu);
+       mutex_lock(&therm_cpu_lock);
+       switch (action) {
+       case CPU_ONLINE:
+               thermal_throttle_add_dev(sys_dev);
+               break;
+       case CPU_DEAD:
+               thermal_throttle_remove_dev(sys_dev);
+               break;
+       }
+       mutex_unlock(&therm_cpu_lock);
+       return NOTIFY_OK;
+}
+
+static struct notifier_block thermal_throttle_cpu_notifier =
+{
+       .notifier_call = thermal_throttle_cpu_callback,
+};
+#endif /* CONFIG_HOTPLUG_CPU */
+
+static __init int thermal_throttle_init_device(void)
+{
+       unsigned int cpu = 0;
+
+       if (!atomic_read(&therm_throt_en))
+               return 0;
+
+       register_hotcpu_notifier(&thermal_throttle_cpu_notifier);
+
+#ifdef CONFIG_HOTPLUG_CPU
+       mutex_lock(&therm_cpu_lock);
+#endif
+       /* connect live CPUs to sysfs */
+       for_each_online_cpu(cpu)
+               thermal_throttle_add_dev(get_cpu_sysdev(cpu));
+#ifdef CONFIG_HOTPLUG_CPU
+       mutex_unlock(&therm_cpu_lock);
+#endif
+
+       return 0;
+}
+
+device_initcall(thermal_throttle_init_device);
+#endif /* CONFIG_SYSFS */
index ad87fa58058d574c7eaa431b2497f82ff60156a8..8bf23cc80c63124a57706253c37e0a9272590991 100644 (file)
@@ -10,7 +10,7 @@
  *     to have CPUID. (Thanks to Herbert Oppmann)
  */
  
-static int __init deep_magic_nexgen_probe(void)
+static int __cpuinit deep_magic_nexgen_probe(void)
 {
        int ret;
        
@@ -27,21 +27,20 @@ static int __init deep_magic_nexgen_probe(void)
        return  ret;
 }
 
-static void __init init_nexgen(struct cpuinfo_x86 * c)
+static void __cpuinit init_nexgen(struct cpuinfo_x86 * c)
 {
        c->x86_cache_size = 256; /* A few had 1 MB... */
 }
 
-static void __init nexgen_identify(struct cpuinfo_x86 * c)
+static void __cpuinit nexgen_identify(struct cpuinfo_x86 * c)
 {
        /* Detect NexGen with old hypercode */
        if ( deep_magic_nexgen_probe() ) {
                strcpy(c->x86_vendor_id, "NexGenDriven");
        }
-       generic_identify(c);
 }
 
-static struct cpu_dev nexgen_cpu_dev __initdata = {
+static struct cpu_dev nexgen_cpu_dev __cpuinitdata = {
        .c_vendor       = "Nexgen",
        .c_ident        = { "NexGenDriven" },
        .c_models = {
index f54a15268ed730d7a24aba1668d140636fb6d88e..76aac088a323de6962de5aeb82ffa7911c8d8265 100644 (file)
@@ -46,8 +46,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
                /* Intel-defined (#2) */
                "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
-               "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
-               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
+               NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* VIA/Cyrix/Centaur-defined */
index d08d5a2811c83cb85d05c697293985b86c86de42..9317f74149893693f4ea735a352ff6f965441e0c 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "cpu.h"
 
-static void __init init_rise(struct cpuinfo_x86 *c)
+static void __cpuinit init_rise(struct cpuinfo_x86 *c)
 {
        printk("CPU: Rise iDragon");
        if (c->x86_model > 2)
@@ -28,7 +28,7 @@ static void __init init_rise(struct cpuinfo_x86 *c)
        set_bit(X86_FEATURE_CX8, c->x86_capability);
 }
 
-static struct cpu_dev rise_cpu_dev __initdata = {
+static struct cpu_dev rise_cpu_dev __cpuinitdata = {
        .c_vendor       = "Rise",
        .c_ident        = { "RiseRiseRise" },
        .c_models = {
index 7214c9b577ab91329ecdb261926e2cdde6e729fd..4056fb7d2cdfdbb137f4b1e40ddab1a908d6ca0b 100644 (file)
@@ -5,7 +5,7 @@
 #include <asm/msr.h>
 #include "cpu.h"
 
-static void __init init_transmeta(struct cpuinfo_x86 *c)
+static void __cpuinit init_transmeta(struct cpuinfo_x86 *c)
 {
        unsigned int cap_mask, uk, max, dummy;
        unsigned int cms_rev1, cms_rev2;
@@ -85,10 +85,9 @@ static void __init init_transmeta(struct cpuinfo_x86 *c)
 #endif
 }
 
-static void __init transmeta_identify(struct cpuinfo_x86 * c)
+static void __cpuinit transmeta_identify(struct cpuinfo_x86 * c)
 {
        u32 xlvl;
-       generic_identify(c);
 
        /* Transmeta-defined flags: level 0x80860001 */
        xlvl = cpuid_eax(0x80860000);
@@ -98,7 +97,7 @@ static void __init transmeta_identify(struct cpuinfo_x86 * c)
        }
 }
 
-static struct cpu_dev transmeta_cpu_dev __initdata = {
+static struct cpu_dev transmeta_cpu_dev __cpuinitdata = {
        .c_vendor       = "Transmeta",
        .c_ident        = { "GenuineTMx86", "TransmetaCPU" },
        .c_init         = init_transmeta,
index 2cd988f6dc556c4bd5f415f93de77d12c1b5e8cf..1bf3f87e9c5b66cb244c3f6d9902b35701ef9d8e 100644 (file)
@@ -5,12 +5,8 @@
 
 /* UMC chips appear to be only either 386 or 486, so no special init takes place.
  */
-static void __init init_umc(struct cpuinfo_x86 * c)
-{
-
-}
 
-static struct cpu_dev umc_cpu_dev __initdata = {
+static struct cpu_dev umc_cpu_dev __cpuinitdata = {
        .c_vendor       = "UMC",
        .c_ident        = { "UMC UMC UMC" },
        .c_models = {
@@ -21,7 +17,6 @@ static struct cpu_dev umc_cpu_dev __initdata = {
                  }
                },
        },
-       .c_init         = init_umc,
 };
 
 int __init umc_init_cpu(void)
index 5b96f038367f4481dca597f7c32e771efbf3fcfc..67d297dc1003cd0d1fec64ade9fba9fd4218a33f 100644 (file)
@@ -22,6 +22,8 @@
 #include <asm/nmi.h>
 #include <asm/hw_irq.h>
 #include <asm/apic.h>
+#include <asm/kdebug.h>
+
 #include <mach_ipi.h>
 
 
@@ -93,16 +95,25 @@ static void crash_save_self(struct pt_regs *regs)
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
 static atomic_t waiting_for_crash_ipi;
 
-static int crash_nmi_callback(struct pt_regs *regs, int cpu)
+static int crash_nmi_callback(struct notifier_block *self,
+                       unsigned long val, void *data)
 {
+       struct pt_regs *regs;
        struct pt_regs fixed_regs;
+       int cpu;
+
+       if (val != DIE_NMI_IPI)
+               return NOTIFY_OK;
+
+       regs = ((struct die_args *)data)->regs;
+       cpu = raw_smp_processor_id();
 
        /* Don't do anything if this handler is invoked on crashing cpu.
         * Otherwise, system will completely hang. Crashing cpu can get
         * an NMI if system was initially booted with nmi_watchdog parameter.
         */
        if (cpu == crashing_cpu)
-               return 1;
+               return NOTIFY_STOP;
        local_irq_disable();
 
        if (!user_mode_vm(regs)) {
@@ -125,13 +136,18 @@ static void smp_send_nmi_allbutself(void)
        send_IPI_allbutself(NMI_VECTOR);
 }
 
+static struct notifier_block crash_nmi_nb = {
+       .notifier_call = crash_nmi_callback,
+};
+
 static void nmi_shootdown_cpus(void)
 {
        unsigned long msecs;
 
        atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
        /* Would it be better to replace the trap vector here? */
-       set_nmi_callback(crash_nmi_callback);
+       if (register_die_notifier(&crash_nmi_nb))
+               return;         /* return what? */
        /* Ensure the new callback function is set before sending
         * out the NMI
         */
index 87f9f60b803be12deb178df607c169a6cb333afb..5a63d6fdb70e4ff75d09b69874334b758d5af07a 100644 (file)
@@ -76,8 +76,15 @@ DF_MASK              = 0x00000400
 NT_MASK                = 0x00004000
 VM_MASK                = 0x00020000
 
+/* These are replaces for paravirtualization */
+#define DISABLE_INTERRUPTS             cli
+#define ENABLE_INTERRUPTS              sti
+#define ENABLE_INTERRUPTS_SYSEXIT      sti; sysexit
+#define INTERRUPT_RETURN               iret
+#define GET_CR0_INTO_EAX               movl %cr0, %eax
+
 #ifdef CONFIG_PREEMPT
-#define preempt_stop           cli; TRACE_IRQS_OFF
+#define preempt_stop           DISABLE_INTERRUPTS; TRACE_IRQS_OFF
 #else
 #define preempt_stop
 #define resume_kernel          restore_nocheck
@@ -176,18 +183,21 @@ VM_MASK           = 0x00020000
 
 #define RING0_INT_FRAME \
        CFI_STARTPROC simple;\
+       CFI_SIGNAL_FRAME;\
        CFI_DEF_CFA esp, 3*4;\
        /*CFI_OFFSET cs, -2*4;*/\
        CFI_OFFSET eip, -3*4
 
 #define RING0_EC_FRAME \
        CFI_STARTPROC simple;\
+       CFI_SIGNAL_FRAME;\
        CFI_DEF_CFA esp, 4*4;\
        /*CFI_OFFSET cs, -2*4;*/\
        CFI_OFFSET eip, -3*4
 
 #define RING0_PTREGS_FRAME \
        CFI_STARTPROC simple;\
+       CFI_SIGNAL_FRAME;\
        CFI_DEF_CFA esp, OLDESP-EBX;\
        /*CFI_OFFSET cs, CS-OLDESP;*/\
        CFI_OFFSET eip, EIP-OLDESP;\
@@ -233,10 +243,11 @@ ret_from_intr:
 check_userspace:
        movl EFLAGS(%esp), %eax         # mix EFLAGS and CS
        movb CS(%esp), %al
-       testl $(VM_MASK | 3), %eax
-       jz resume_kernel
+       andl $(VM_MASK | SEGMENT_RPL_MASK), %eax
+       cmpl $USER_RPL, %eax
+       jb resume_kernel                # not returning to v8086 or userspace
 ENTRY(resume_userspace)
-       cli                             # make sure we don't miss an interrupt
+       DISABLE_INTERRUPTS              # make sure we don't miss an interrupt
                                        # setting need_resched or sigpending
                                        # between sampling and the iret
        movl TI_flags(%ebp), %ecx
@@ -247,7 +258,7 @@ ENTRY(resume_userspace)
 
 #ifdef CONFIG_PREEMPT
 ENTRY(resume_kernel)
-       cli
+       DISABLE_INTERRUPTS
        cmpl $0,TI_preempt_count(%ebp)  # non-zero preempt_count ?
        jnz restore_nocheck
 need_resched:
@@ -267,6 +278,7 @@ need_resched:
        # sysenter call handler stub
 ENTRY(sysenter_entry)
        CFI_STARTPROC simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA esp, 0
        CFI_REGISTER esp, ebp
        movl TSS_sysenter_esp0(%esp),%esp
@@ -275,7 +287,7 @@ sysenter_past_esp:
         * No need to follow this irqs on/off section: the syscall
         * disabled irqs and here we enable it straight after entry:
         */
-       sti
+       ENABLE_INTERRUPTS
        pushl $(__USER_DS)
        CFI_ADJUST_CFA_OFFSET 4
        /*CFI_REL_OFFSET ss, 0*/
@@ -320,7 +332,7 @@ sysenter_past_esp:
        jae syscall_badsys
        call *sys_call_table(,%eax,4)
        movl %eax,EAX(%esp)
-       cli
+       DISABLE_INTERRUPTS
        TRACE_IRQS_OFF
        movl TI_flags(%ebp), %ecx
        testw $_TIF_ALLWORK_MASK, %cx
@@ -330,8 +342,7 @@ sysenter_past_esp:
        movl OLDESP(%esp), %ecx
        xorl %ebp,%ebp
        TRACE_IRQS_ON
-       sti
-       sysexit
+       ENABLE_INTERRUPTS_SYSEXIT
        CFI_ENDPROC
 
 
@@ -356,7 +367,7 @@ syscall_call:
        call *sys_call_table(,%eax,4)
        movl %eax,EAX(%esp)             # store the return value
 syscall_exit:
-       cli                             # make sure we don't miss an interrupt
+       DISABLE_INTERRUPTS              # make sure we don't miss an interrupt
                                        # setting need_resched or sigpending
                                        # between sampling and the iret
        TRACE_IRQS_OFF
@@ -371,8 +382,8 @@ restore_all:
        # See comments in process.c:copy_thread() for details.
        movb OLDSS(%esp), %ah
        movb CS(%esp), %al
-       andl $(VM_MASK | (4 << 8) | 3), %eax
-       cmpl $((4 << 8) | 3), %eax
+       andl $(VM_MASK | (SEGMENT_TI_MASK << 8) | SEGMENT_RPL_MASK), %eax
+       cmpl $((SEGMENT_LDT << 8) | USER_RPL), %eax
        CFI_REMEMBER_STATE
        je ldt_ss                       # returning to user-space with LDT SS
 restore_nocheck:
@@ -381,11 +392,11 @@ restore_nocheck_notrace:
        RESTORE_REGS
        addl $4, %esp
        CFI_ADJUST_CFA_OFFSET -4
-1:     iret
+1:     INTERRUPT_RETURN
 .section .fixup,"ax"
 iret_exc:
        TRACE_IRQS_ON
-       sti
+       ENABLE_INTERRUPTS
        pushl $0                        # no error code
        pushl $do_iret_error
        jmp error_code
@@ -409,7 +420,7 @@ ldt_ss:
         * dosemu and wine happy. */
        subl $8, %esp           # reserve space for switch16 pointer
        CFI_ADJUST_CFA_OFFSET 8
-       cli
+       DISABLE_INTERRUPTS
        TRACE_IRQS_OFF
        movl %esp, %eax
        /* Set up the 16bit stack frame with switch32 pointer on top,
@@ -419,7 +430,7 @@ ldt_ss:
        TRACE_IRQS_IRET
        RESTORE_REGS
        lss 20+4(%esp), %esp    # switch to 16bit stack
-1:     iret
+1:     INTERRUPT_RETURN
 .section __ex_table,"a"
        .align 4
        .long 1b,iret_exc
@@ -434,7 +445,7 @@ work_pending:
        jz work_notifysig
 work_resched:
        call schedule
-       cli                             # make sure we don't miss an interrupt
+       DISABLE_INTERRUPTS              # make sure we don't miss an interrupt
                                        # setting need_resched or sigpending
                                        # between sampling and the iret
        TRACE_IRQS_OFF
@@ -490,7 +501,7 @@ syscall_exit_work:
        testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP), %cl
        jz work_pending
        TRACE_IRQS_ON
-       sti                             # could let do_syscall_trace() call
+       ENABLE_INTERRUPTS               # could let do_syscall_trace() call
                                        # schedule() instead
        movl %esp, %eax
        movl $1, %edx
@@ -591,11 +602,9 @@ ENTRY(name)                                \
 /* The include is where all of the SMP etc. interrupts come from */
 #include "entry_arch.h"
 
-ENTRY(divide_error)
-       RING0_INT_FRAME
-       pushl $0                        # no error code
-       CFI_ADJUST_CFA_OFFSET 4
-       pushl $do_divide_error
+KPROBE_ENTRY(page_fault)
+       RING0_EC_FRAME
+       pushl $do_page_fault
        CFI_ADJUST_CFA_OFFSET 4
        ALIGN
 error_code:
@@ -645,6 +654,7 @@ error_code:
        call *%edi
        jmp ret_from_exception
        CFI_ENDPROC
+KPROBE_END(page_fault)
 
 ENTRY(coprocessor_error)
        RING0_INT_FRAME
@@ -669,7 +679,7 @@ ENTRY(device_not_available)
        pushl $-1                       # mark this as an int
        CFI_ADJUST_CFA_OFFSET 4
        SAVE_ALL
-       movl %cr0, %eax
+       GET_CR0_INTO_EAX
        testl $0x4, %eax                # EM (math emulation bit)
        jne device_not_available_emulate
        preempt_stop
@@ -702,9 +712,15 @@ device_not_available_emulate:
        jne ok;                                 \
 label:                                         \
        movl TSS_sysenter_esp0+offset(%esp),%esp;       \
+       CFI_DEF_CFA esp, 0;                     \
+       CFI_UNDEFINED eip;                      \
        pushfl;                                 \
+       CFI_ADJUST_CFA_OFFSET 4;                \
        pushl $__KERNEL_CS;                     \
-       pushl $sysenter_past_esp
+       CFI_ADJUST_CFA_OFFSET 4;                \
+       pushl $sysenter_past_esp;               \
+       CFI_ADJUST_CFA_OFFSET 4;                \
+       CFI_REL_OFFSET eip, 0
 
 KPROBE_ENTRY(debug)
        RING0_INT_FRAME
@@ -720,7 +736,8 @@ debug_stack_correct:
        call do_debug
        jmp ret_from_exception
        CFI_ENDPROC
-       .previous .text
+KPROBE_END(debug)
+
 /*
  * NMI is doubly nasty. It can happen _while_ we're handling
  * a debug fault, and the debug fault hasn't yet been able to
@@ -729,7 +746,7 @@ debug_stack_correct:
  * check whether we got an NMI on the debug path where the debug
  * fault happened on the sysenter path.
  */
-ENTRY(nmi)
+KPROBE_ENTRY(nmi)
        RING0_INT_FRAME
        pushl %eax
        CFI_ADJUST_CFA_OFFSET 4
@@ -754,6 +771,7 @@ ENTRY(nmi)
        cmpl $sysenter_entry,12(%esp)
        je nmi_debug_stack_check
 nmi_stack_correct:
+       /* We have a RING0_INT_FRAME here */
        pushl %eax
        CFI_ADJUST_CFA_OFFSET 4
        SAVE_ALL
@@ -764,9 +782,12 @@ nmi_stack_correct:
        CFI_ENDPROC
 
 nmi_stack_fixup:
+       RING0_INT_FRAME
        FIX_STACK(12,nmi_stack_correct, 1)
        jmp nmi_stack_correct
+
 nmi_debug_stack_check:
+       /* We have a RING0_INT_FRAME here */
        cmpw $__KERNEL_CS,16(%esp)
        jne nmi_stack_correct
        cmpl $debug,(%esp)
@@ -777,8 +798,10 @@ nmi_debug_stack_check:
        jmp nmi_stack_correct
 
 nmi_16bit_stack:
-       RING0_INT_FRAME
-       /* create the pointer to lss back */
+       /* We have a RING0_INT_FRAME here.
+        *
+        * create the pointer to lss back
+        */
        pushl %ss
        CFI_ADJUST_CFA_OFFSET 4
        pushl %esp
@@ -799,12 +822,13 @@ nmi_16bit_stack:
        call do_nmi
        RESTORE_REGS
        lss 12+4(%esp), %esp            # back to 16bit stack
-1:     iret
+1:     INTERRUPT_RETURN
        CFI_ENDPROC
 .section __ex_table,"a"
        .align 4
        .long 1b,iret_exc
 .previous
+KPROBE_END(nmi)
 
 KPROBE_ENTRY(int3)
        RING0_INT_FRAME
@@ -816,7 +840,7 @@ KPROBE_ENTRY(int3)
        call do_int3
        jmp ret_from_exception
        CFI_ENDPROC
-       .previous .text
+KPROBE_END(int3)
 
 ENTRY(overflow)
        RING0_INT_FRAME
@@ -881,7 +905,7 @@ KPROBE_ENTRY(general_protection)
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
-       .previous .text
+KPROBE_END(general_protection)
 
 ENTRY(alignment_check)
        RING0_EC_FRAME
@@ -890,13 +914,14 @@ ENTRY(alignment_check)
        jmp error_code
        CFI_ENDPROC
 
-KPROBE_ENTRY(page_fault)
-       RING0_EC_FRAME
-       pushl $do_page_fault
+ENTRY(divide_error)
+       RING0_INT_FRAME
+       pushl $0                        # no error code
+       CFI_ADJUST_CFA_OFFSET 4
+       pushl $do_divide_error
        CFI_ADJUST_CFA_OFFSET 4
        jmp error_code
        CFI_ENDPROC
-       .previous .text
 
 #ifdef CONFIG_X86_MCE
 ENTRY(machine_check)
@@ -949,6 +974,19 @@ ENTRY(arch_unwind_init_running)
 ENDPROC(arch_unwind_init_running)
 #endif
 
+ENTRY(kernel_thread_helper)
+       pushl $0                # fake return address for unwinder
+       CFI_STARTPROC
+       movl %edx,%eax
+       push %edx
+       CFI_ADJUST_CFA_OFFSET 4
+       call *%ebx
+       push %eax
+       CFI_ADJUST_CFA_OFFSET 4
+       call do_exit
+       CFI_ENDPROC
+ENDPROC(kernel_thread_helper)
+
 .section .rodata,"a"
 #include "syscall_table.S"
 
index a6b8bd89aa27192ea507a6c8fee660e414b059b9..be9d883c62ce0302995b56c830530670902a7fe6 100644 (file)
@@ -371,8 +371,65 @@ rp_sidt:
        addl $8,%edi
        dec %ecx
        jne rp_sidt
+
+.macro set_early_handler handler,trapno
+       lea \handler,%edx
+       movl $(__KERNEL_CS << 16),%eax
+       movw %dx,%ax
+       movw $0x8E00,%dx        /* interrupt gate - dpl=0, present */
+       lea idt_table,%edi
+       movl %eax,8*\trapno(%edi)
+       movl %edx,8*\trapno+4(%edi)
+.endm
+
+       set_early_handler handler=early_divide_err,trapno=0
+       set_early_handler handler=early_illegal_opcode,trapno=6
+       set_early_handler handler=early_protection_fault,trapno=13
+       set_early_handler handler=early_page_fault,trapno=14
+
        ret
 
+early_divide_err:
+       xor %edx,%edx
+       pushl $0        /* fake errcode */
+       jmp early_fault
+
+early_illegal_opcode:
+       movl $6,%edx
+       pushl $0        /* fake errcode */
+       jmp early_fault
+
+early_protection_fault:
+       movl $13,%edx
+       jmp early_fault
+
+early_page_fault:
+       movl $14,%edx
+       jmp early_fault
+
+early_fault:
+       cld
+#ifdef CONFIG_PRINTK
+       movl $(__KERNEL_DS),%eax
+       movl %eax,%ds
+       movl %eax,%es
+       cmpl $2,early_recursion_flag
+       je hlt_loop
+       incl early_recursion_flag
+       movl %cr2,%eax
+       pushl %eax
+       pushl %edx              /* trapno */
+       pushl $fault_msg
+#ifdef CONFIG_EARLY_PRINTK
+       call early_printk
+#else
+       call printk
+#endif
+#endif
+hlt_loop:
+       hlt
+       jmp hlt_loop
+
 /* This is the default interrupt "handler" :-) */
        ALIGN
 ignore_int:
@@ -386,6 +443,9 @@ ignore_int:
        movl $(__KERNEL_DS),%eax
        movl %eax,%ds
        movl %eax,%es
+       cmpl $2,early_recursion_flag
+       je hlt_loop
+       incl early_recursion_flag
        pushl 16(%esp)
        pushl 24(%esp)
        pushl 32(%esp)
@@ -431,9 +491,16 @@ ENTRY(stack_start)
 
 ready: .byte 0
 
+early_recursion_flag:
+       .long 0
+
 int_msg:
        .asciz "Unknown interrupt or fault at EIP %p %p %p\n"
 
+fault_msg:
+       .ascii "Int %d: CR2 %p  err %p  EIP %p  CS %p  flags %p\n"
+       .asciz "Stack: %p %p %p %p %p %p %p %p\n"
+
 /*
  * The IDT and GDT 'descriptors' are a strange 48-bit object
  * only used by the lidt and lgdt instructions. They are not
index d4756d154f47b4d10447dba20378fca19d957193..ea5f4e7958d8f072108576fb33000af089d93ab0 100644 (file)
@@ -45,6 +45,8 @@ static void end_8259A_irq (unsigned int irq)
 
 #define shutdown_8259A_irq     disable_8259A_irq
 
+static int i8259A_auto_eoi;
+
 static void mask_and_ack_8259A(unsigned int);
 
 unsigned int startup_8259A_irq(unsigned int irq)
@@ -253,7 +255,7 @@ static void save_ELCR(char *trigger)
 
 static int i8259A_resume(struct sys_device *dev)
 {
-       init_8259A(0);
+       init_8259A(i8259A_auto_eoi);
        restore_ELCR(irq_trigger);
        return 0;
 }
@@ -301,6 +303,8 @@ void init_8259A(int auto_eoi)
 {
        unsigned long flags;
 
+       i8259A_auto_eoi = auto_eoi;
+
        spin_lock_irqsave(&i8259A_lock, flags);
 
        outb(0xff, PIC_MASTER_IMR);     /* mask all of 8259A-1 */
index 4fb32c551fe0b9bb62df93acab0cb80dd657d359..fd0df75cfbdadd3fd19afd2f5aeaf0308d9e96ba 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/nmi.h>
 
 #include <mach_apic.h>
+#include <mach_apicdef.h>
 
 #include "io_ports.h"
 
@@ -65,7 +66,7 @@ int sis_apic_bug = -1;
  */
 int nr_ioapic_registers[MAX_IO_APICS];
 
-int disable_timer_pin_1 __initdata;
+static int disable_timer_pin_1 __initdata;
 
 /*
  * Rough estimation of how many shared IRQs there are, can
@@ -93,6 +94,34 @@ int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
 #define vector_to_irq(vector)  (vector)
 #endif
 
+
+union entry_union {
+       struct { u32 w1, w2; };
+       struct IO_APIC_route_entry entry;
+};
+
+static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
+{
+       union entry_union eu;
+       unsigned long flags;
+       spin_lock_irqsave(&ioapic_lock, flags);
+       eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+       eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+       spin_unlock_irqrestore(&ioapic_lock, flags);
+       return eu.entry;
+}
+
+static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+{
+       unsigned long flags;
+       union entry_union eu;
+       eu.entry = e;
+       spin_lock_irqsave(&ioapic_lock, flags);
+       io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+       io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+       spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
 /*
  * The common case is 1:1 IRQ<->pin mappings. Sometimes there are
  * shared ISA-space IRQs, so we have to support them. We are super
@@ -200,13 +229,9 @@ static void unmask_IO_APIC_irq (unsigned int irq)
 static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
 {
        struct IO_APIC_route_entry entry;
-       unsigned long flags;
        
        /* Check delivery_mode to be sure we're not clearing an SMI pin */
-       spin_lock_irqsave(&ioapic_lock, flags);
-       *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
-       *(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       entry = ioapic_read_entry(apic, pin);
        if (entry.delivery_mode == dest_SMI)
                return;
 
@@ -215,10 +240,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
         */
        memset(&entry, 0, sizeof(entry));
        entry.mask = 1;
-       spin_lock_irqsave(&ioapic_lock, flags);
-       io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
-       io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       ioapic_write_entry(apic, pin, entry);
 }
 
 static void clear_IO_APIC (void)
@@ -1283,9 +1305,8 @@ static void __init setup_IO_APIC_irqs(void)
                        if (!apic && (irq < 16))
                                disable_8259A_irq(irq);
                }
+               ioapic_write_entry(apic, pin, entry);
                spin_lock_irqsave(&ioapic_lock, flags);
-               io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
-               io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
                set_native_irq_info(irq, TARGET_CPUS);
                spin_unlock_irqrestore(&ioapic_lock, flags);
        }
@@ -1301,7 +1322,6 @@ static void __init setup_IO_APIC_irqs(void)
 static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, int vector)
 {
        struct IO_APIC_route_entry entry;
-       unsigned long flags;
 
        memset(&entry,0,sizeof(entry));
 
@@ -1331,10 +1351,7 @@ static void __init setup_ExtINT_IRQ0_pin(unsigned int apic, unsigned int pin, in
        /*
         * Add it to the IO-APIC irq-routing table:
         */
-       spin_lock_irqsave(&ioapic_lock, flags);
-       io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
-       io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       ioapic_write_entry(apic, pin, entry);
 
        enable_8259A_irq(0);
 }
@@ -1444,10 +1461,7 @@ void __init print_IO_APIC(void)
        for (i = 0; i <= reg_01.bits.entries; i++) {
                struct IO_APIC_route_entry entry;
 
-               spin_lock_irqsave(&ioapic_lock, flags);
-               *(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
-               *(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
+               entry = ioapic_read_entry(apic, i);
 
                printk(KERN_DEBUG " %02x %03X %02X  ",
                        i,
@@ -1666,10 +1680,7 @@ static void __init enable_IO_APIC(void)
                /* See if any of the pins is in ExtINT mode */
                for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
                        struct IO_APIC_route_entry entry;
-                       spin_lock_irqsave(&ioapic_lock, flags);
-                       *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
-                       *(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
-                       spin_unlock_irqrestore(&ioapic_lock, flags);
+                       entry = ioapic_read_entry(apic, pin);
 
 
                        /* If the interrupt line is enabled and in ExtInt mode
@@ -1726,7 +1737,6 @@ void disable_IO_APIC(void)
         */
        if (ioapic_i8259.pin != -1) {
                struct IO_APIC_route_entry entry;
-               unsigned long flags;
 
                memset(&entry, 0, sizeof(entry));
                entry.mask            = 0; /* Enabled */
@@ -1743,12 +1753,7 @@ void disable_IO_APIC(void)
                /*
                 * Add it to the IO-APIC irq-routing table:
                 */
-               spin_lock_irqsave(&ioapic_lock, flags);
-               io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
-                       *(((int *)&entry)+1));
-               io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
-                       *(((int *)&entry)+0));
-               spin_unlock_irqrestore(&ioapic_lock, flags);
+               ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
        }
        disconnect_bsp_APIC(ioapic_i8259.pin != -1);
 }
@@ -2213,17 +2218,13 @@ static inline void unlock_ExtINT_logic(void)
        int apic, pin, i;
        struct IO_APIC_route_entry entry0, entry1;
        unsigned char save_control, save_freq_select;
-       unsigned long flags;
 
        pin  = find_isa_irq_pin(8, mp_INT);
        apic = find_isa_irq_apic(8, mp_INT);
        if (pin == -1)
                return;
 
-       spin_lock_irqsave(&ioapic_lock, flags);
-       *(((int *)&entry0) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
-       *(((int *)&entry0) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       entry0 = ioapic_read_entry(apic, pin);
        clear_IO_APIC_pin(apic, pin);
 
        memset(&entry1, 0, sizeof(entry1));
@@ -2236,10 +2237,7 @@ static inline void unlock_ExtINT_logic(void)
        entry1.trigger = 0;
        entry1.vector = 0;
 
-       spin_lock_irqsave(&ioapic_lock, flags);
-       io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry1) + 1));
-       io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry1) + 0));
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       ioapic_write_entry(apic, pin, entry1);
 
        save_control = CMOS_READ(RTC_CONTROL);
        save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
@@ -2258,10 +2256,7 @@ static inline void unlock_ExtINT_logic(void)
        CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
        clear_IO_APIC_pin(apic, pin);
 
-       spin_lock_irqsave(&ioapic_lock, flags);
-       io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry0) + 1));
-       io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry0) + 0));
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       ioapic_write_entry(apic, pin, entry0);
 }
 
 int timer_uses_ioapic_pin_0;
@@ -2461,17 +2456,12 @@ static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
 {
        struct IO_APIC_route_entry *entry;
        struct sysfs_ioapic_data *data;
-       unsigned long flags;
        int i;
        
        data = container_of(dev, struct sysfs_ioapic_data, dev);
        entry = data->entry;
-       spin_lock_irqsave(&ioapic_lock, flags);
-       for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
-               *(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
-               *(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
-       }
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       for (i = 0; i < nr_ioapic_registers[dev->id]; i ++)
+               entry[i] = ioapic_read_entry(dev->id, i);
 
        return 0;
 }
@@ -2493,11 +2483,9 @@ static int ioapic_resume(struct sys_device *dev)
                reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
                io_apic_write(dev->id, 0, reg_00.raw);
        }
-       for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
-               io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
-               io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
-       }
        spin_unlock_irqrestore(&ioapic_lock, flags);
+       for (i = 0; i < nr_ioapic_registers[dev->id]; i ++)
+               ioapic_write_entry(dev->id, i, entry[i]);
 
        return 0;
 }
@@ -2694,9 +2682,8 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
        if (!ioapic && (irq < 16))
                disable_8259A_irq(irq);
 
+       ioapic_write_entry(ioapic, pin, entry);
        spin_lock_irqsave(&ioapic_lock, flags);
-       io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
-       io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
        set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
        spin_unlock_irqrestore(&ioapic_lock, flags);
 
@@ -2704,3 +2691,25 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
 }
 
 #endif /* CONFIG_ACPI */
+
+static int __init parse_disable_timer_pin_1(char *arg)
+{
+       disable_timer_pin_1 = 1;
+       return 0;
+}
+early_param("disable_timer_pin_1", parse_disable_timer_pin_1);
+
+static int __init parse_enable_timer_pin_1(char *arg)
+{
+       disable_timer_pin_1 = -1;
+       return 0;
+}
+early_param("enable_timer_pin_1", parse_enable_timer_pin_1);
+
+static int __init parse_noapic(char *arg)
+{
+       /* disable IO-APIC */
+       disable_ioapic_setup();
+       return 0;
+}
+early_param("noapic", parse_noapic);
index 6b1ae6ba76f0d15421f9aee87747a9192da1f4db..91966bafb3dc7efe54fb1f73d368e1a192c5c7cf 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/kexec.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/system.h>
 
 #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
-
-#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
-#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
-#define L2_ATTR (_PAGE_PRESENT)
-
-#define LEVEL0_SIZE (1UL << 12UL)
-
-#ifndef CONFIG_X86_PAE
-#define LEVEL1_SIZE (1UL << 22UL)
-static u32 pgtable_level1[1024] PAGE_ALIGNED;
-
-static void identity_map_page(unsigned long address)
-{
-       unsigned long level1_index, level2_index;
-       u32 *pgtable_level2;
-
-       /* Find the current page table */
-       pgtable_level2 = __va(read_cr3());
-
-       /* Find the indexes of the physical address to identity map */
-       level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
-       level2_index = address / LEVEL1_SIZE;
-
-       /* Identity map the page table entry */
-       pgtable_level1[level1_index] = address | L0_ATTR;
-       pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
-
-       /* Flush the tlb so the new mapping takes effect.
-        * Global tlb entries are not flushed but that is not an issue.
-        */
-       load_cr3(pgtable_level2);
-}
-
-#else
-#define LEVEL1_SIZE (1UL << 21UL)
-#define LEVEL2_SIZE (1UL << 30UL)
-static u64 pgtable_level1[512] PAGE_ALIGNED;
-static u64 pgtable_level2[512] PAGE_ALIGNED;
-
-static void identity_map_page(unsigned long address)
-{
-       unsigned long level1_index, level2_index, level3_index;
-       u64 *pgtable_level3;
-
-       /* Find the current page table */
-       pgtable_level3 = __va(read_cr3());
-
-       /* Find the indexes of the physical address to identity map */
-       level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
-       level2_index = (address % LEVEL2_SIZE)/LEVEL1_SIZE;
-       level3_index = address / LEVEL2_SIZE;
-
-       /* Identity map the page table entry */
-       pgtable_level1[level1_index] = address | L0_ATTR;
-       pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
-       set_64bit(&pgtable_level3[level3_index],
-                                              __pa(pgtable_level2) | L2_ATTR);
-
-       /* Flush the tlb so the new mapping takes effect.
-        * Global tlb entries are not flushed but that is not an issue.
-        */
-       load_cr3(pgtable_level3);
-}
+static u32 kexec_pgd[1024] PAGE_ALIGNED;
+#ifdef CONFIG_X86_PAE
+static u32 kexec_pmd0[1024] PAGE_ALIGNED;
+static u32 kexec_pmd1[1024] PAGE_ALIGNED;
 #endif
+static u32 kexec_pte0[1024] PAGE_ALIGNED;
+static u32 kexec_pte1[1024] PAGE_ALIGNED;
 
 static void set_idt(void *newidt, __u16 limit)
 {
@@ -127,16 +71,6 @@ static void load_segments(void)
 #undef __STR
 }
 
-typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
-                                       unsigned long indirection_page,
-                                       unsigned long reboot_code_buffer,
-                                       unsigned long start_address,
-                                       unsigned int has_pae) ATTRIB_NORET;
-
-extern const unsigned char relocate_new_kernel[];
-extern void relocate_new_kernel_end(void);
-extern const unsigned int relocate_new_kernel_size;
-
 /*
  * A architecture hook called to validate the
  * proposed image and prepare the control pages
@@ -169,25 +103,29 @@ void machine_kexec_cleanup(struct kimage *image)
  */
 NORET_TYPE void machine_kexec(struct kimage *image)
 {
-       unsigned long page_list;
-       unsigned long reboot_code_buffer;
-
-       relocate_new_kernel_t rnk;
+       unsigned long page_list[PAGES_NR];
+       void *control_page;
 
        /* Interrupts aren't acceptable while we reboot */
        local_irq_disable();
 
-       /* Compute some offsets */
-       reboot_code_buffer = page_to_pfn(image->control_code_page)
-                                                               << PAGE_SHIFT;
-       page_list = image->head;
-
-       /* Set up an identity mapping for the reboot_code_buffer */
-       identity_map_page(reboot_code_buffer);
-
-       /* copy it out */
-       memcpy((void *)reboot_code_buffer, relocate_new_kernel,
-                                               relocate_new_kernel_size);
+       control_page = page_address(image->control_code_page);
+       memcpy(control_page, relocate_kernel, PAGE_SIZE);
+
+       page_list[PA_CONTROL_PAGE] = __pa(control_page);
+       page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel;
+       page_list[PA_PGD] = __pa(kexec_pgd);
+       page_list[VA_PGD] = (unsigned long)kexec_pgd;
+#ifdef CONFIG_X86_PAE
+       page_list[PA_PMD_0] = __pa(kexec_pmd0);
+       page_list[VA_PMD_0] = (unsigned long)kexec_pmd0;
+       page_list[PA_PMD_1] = __pa(kexec_pmd1);
+       page_list[VA_PMD_1] = (unsigned long)kexec_pmd1;
+#endif
+       page_list[PA_PTE_0] = __pa(kexec_pte0);
+       page_list[VA_PTE_0] = (unsigned long)kexec_pte0;
+       page_list[PA_PTE_1] = __pa(kexec_pte1);
+       page_list[VA_PTE_1] = (unsigned long)kexec_pte1;
 
        /* The segment registers are funny things, they have both a
         * visible and an invisible part.  Whenever the visible part is
@@ -206,6 +144,28 @@ NORET_TYPE void machine_kexec(struct kimage *image)
        set_idt(phys_to_virt(0),0);
 
        /* now call it */
-       rnk = (relocate_new_kernel_t) reboot_code_buffer;
-       (*rnk)(page_list, reboot_code_buffer, image->start, cpu_has_pae);
+       relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
+                       image->start, cpu_has_pae);
+}
+
+/* crashkernel=size@addr specifies the location to reserve for
+ * a crash kernel.  By reserving this memory we guarantee
+ * that linux never sets it up as a DMA target.
+ * Useful for holding code to do something appropriate
+ * after a kernel panic.
+ */
+static int __init parse_crashkernel(char *arg)
+{
+       unsigned long size, base;
+       size = memparse(arg, &arg);
+       if (*arg == '@') {
+               base = memparse(arg+1, &arg);
+               /* FIXME: Do I want a sanity check
+                * to validate the memory range?
+                */
+               crashk_res.start = base;
+               crashk_res.end   = base + size - 1;
+       }
+       return 0;
 }
+early_param("crashkernel", parse_crashkernel);
index cd5456f14af4bb16eb83adb53bf22592ed47eb38..eb57a851789dc9061aeacf0a2a83813a45f93be6 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/mca.h>
+#include <linux/kprobes.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <linux/proc_fs.h>
@@ -414,7 +415,8 @@ subsys_initcall(mca_init);
 
 /*--------------------------------------------------------------------*/
 
-static void mca_handle_nmi_device(struct mca_device *mca_dev, int check_flag)
+static __kprobes void
+mca_handle_nmi_device(struct mca_device *mca_dev, int check_flag)
 {
        int slot = mca_dev->slot;
 
@@ -444,7 +446,7 @@ static void mca_handle_nmi_device(struct mca_device *mca_dev, int check_flag)
 
 /*--------------------------------------------------------------------*/
 
-static int mca_handle_nmi_callback(struct device *dev, void *data)
+static int __kprobes mca_handle_nmi_callback(struct device *dev, void *data)
 {
        struct mca_device *mca_dev = to_mca_device(dev);
        unsigned char pos5;
@@ -462,7 +464,7 @@ static int mca_handle_nmi_callback(struct device *dev, void *data)
        return 0;
 }
 
-void mca_handle_nmi(void)
+void __kprobes mca_handle_nmi(void)
 {
        /* First try - scan the various adapters and see if a specific
         * adapter was responsible for the error.
index 40b44cc0d14b048523f8bbf0c6935342a6067e3e..9b9479768d5ebcda920044781234b8aa2d4183d3 100644 (file)
@@ -2,6 +2,7 @@
  *     Intel CPU Microcode Update Driver for Linux
  *
  *     Copyright (C) 2000-2004 Tigran Aivazian
+ *                   2006      Shaohua Li <shaohua.li@intel.com>
  *
  *     This driver allows to upgrade microcode on Intel processors
  *     belonging to IA-32 family - PentiumPro, Pentium II, 
@@ -82,6 +83,9 @@
 #include <linux/spinlock.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
+#include <linux/cpu.h>
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
 
 #include <asm/msr.h>
 #include <asm/uaccess.h>
@@ -91,9 +95,6 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
 MODULE_LICENSE("GPL");
 
-static int verbose;
-module_param(verbose, int, 0644);
-
 #define MICROCODE_VERSION      "1.14a"
 
 #define DEFAULT_UCODE_DATASIZE         (2000)    /* 2000 bytes */
@@ -120,55 +121,40 @@ static DEFINE_SPINLOCK(microcode_update_lock);
 /* no concurrent ->write()s are allowed on /dev/cpu/microcode */
 static DEFINE_MUTEX(microcode_mutex);
 
-static void __user *user_buffer;       /* user area microcode data buffer */
-static unsigned int user_buffer_size;  /* it's size */
-
-typedef enum mc_error_code {
-       MC_SUCCESS      = 0,
-       MC_IGNORED      = 1,
-       MC_NOTFOUND     = 2,
-       MC_MARKED       = 3,
-       MC_ALLOCATED    = 4,
-} mc_error_code_t;
-
 static struct ucode_cpu_info {
+       int valid;
        unsigned int sig;
-       unsigned int pf, orig_pf;
+       unsigned int pf;
        unsigned int rev;
-       unsigned int cksum;
-       mc_error_code_t err;
        microcode_t *mc;
 } ucode_cpu_info[NR_CPUS];
-                               
-static int microcode_open (struct inode *unused1, struct file *unused2)
-{
-       return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
-}
 
-static void collect_cpu_info (void *unused)
+static void collect_cpu_info(int cpu_num)
 {
-       int cpu_num = smp_processor_id();
        struct cpuinfo_x86 *c = cpu_data + cpu_num;
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
        unsigned int val[2];
 
-       uci->sig = uci->pf = uci->rev = uci->cksum = 0;
-       uci->err = MC_NOTFOUND; 
+       /* We should bind the task to the CPU */
+       BUG_ON(raw_smp_processor_id() != cpu_num);
+       uci->pf = uci->rev = 0;
        uci->mc = NULL;
+       uci->valid = 1;
 
        if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
                cpu_has(c, X86_FEATURE_IA64)) {
-               printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num);
+               printk(KERN_ERR "microcode: CPU%d not a capable Intel "
+                       "processor\n", cpu_num);
+               uci->valid = 0;
                return;
-       } else {
-               uci->sig = cpuid_eax(0x00000001);
+       }
 
-               if ((c->x86_model >= 5) || (c->x86 > 6)) {
-                       /* get processor flags from MSR 0x17 */
-                       rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
-                       uci->pf = 1 << ((val[1] >> 18) & 7);
-               }
-               uci->orig_pf = uci->pf;
+       uci->sig = cpuid_eax(0x00000001);
+
+       if ((c->x86_model >= 5) || (c->x86 > 6)) {
+               /* get processor flags from MSR 0x17 */
+               rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
+               uci->pf = 1 << ((val[1] >> 18) & 7);
        }
 
        wrmsr(MSR_IA32_UCODE_REV, 0, 0);
@@ -180,218 +166,159 @@ static void collect_cpu_info (void *unused)
                        uci->sig, uci->pf, uci->rev);
 }
 
-static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_header, int sig, int pf, int cksum)
+static inline int microcode_update_match(int cpu_num,
+       microcode_header_t *mc_header, int sig, int pf)
 {
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 
-       pr_debug("Microcode Found.\n");
-       pr_debug("   Header Revision 0x%x\n", mc_header->hdrver);
-       pr_debug("   Loader Revision 0x%x\n", mc_header->ldrver);
-       pr_debug("   Revision 0x%x \n", mc_header->rev);
-       pr_debug("   Date %x/%x/%x\n",
-               ((mc_header->date >> 24 ) & 0xff),
-               ((mc_header->date >> 16 ) & 0xff),
-               (mc_header->date & 0xFFFF));
-       pr_debug("   Signature 0x%x\n", sig);
-       pr_debug("   Type 0x%x Family 0x%x Model 0x%x Stepping 0x%x\n",
-               ((sig >> 12) & 0x3),
-               ((sig >> 8) & 0xf),
-               ((sig >> 4) & 0xf),
-               ((sig & 0xf)));
-       pr_debug("   Processor Flags 0x%x\n", pf);
-       pr_debug("   Checksum 0x%x\n", cksum);
-
-       if (mc_header->rev < uci->rev) {
-               if (uci->err == MC_NOTFOUND) {
-                       uci->err = MC_IGNORED;
-                       uci->cksum = mc_header->rev;
-               } else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev)
-                       uci->cksum = mc_header->rev;
-       } else if (mc_header->rev == uci->rev) {
-               if (uci->err < MC_MARKED) {
-                       /* notify the caller of success on this cpu */
-                       uci->err = MC_SUCCESS;
-               }
-       } else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) {
-               pr_debug("microcode: CPU%d found a matching microcode update with "
-                       " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
-               uci->cksum = cksum;
-               uci->pf = pf; /* keep the original mc pf for cksum calculation */
-               uci->err = MC_MARKED; /* found the match */
-               for_each_online_cpu(cpu_num) {
-                       if (ucode_cpu_info + cpu_num != uci
-                           && ucode_cpu_info[cpu_num].mc == uci->mc) {
-                               uci->mc = NULL;
-                               break;
-                       }
-               }
-               if (uci->mc != NULL) {
-                       vfree(uci->mc);
-                       uci->mc = NULL;
-               }
-       }
-       return;
+       if (!sigmatch(sig, uci->sig, pf, uci->pf)
+               || mc_header->rev <= uci->rev)
+               return 0;
+       return 1;
 }
 
-static int find_matching_ucodes (void) 
+static int microcode_sanity_check(void *mc)
 {
-       int cursor = 0;
-       int error = 0;
-
-       while (cursor + MC_HEADER_SIZE < user_buffer_size) {
-               microcode_header_t mc_header;
-               void *newmc = NULL;
-               int i, sum, cpu_num, allocated_flag, total_size, data_size, ext_table_size;
+       microcode_header_t *mc_header = mc;
+       struct extended_sigtable *ext_header = NULL;
+       struct extended_signature *ext_sig;
+       unsigned long total_size, data_size, ext_table_size;
+       int sum, orig_sum, ext_sigcount = 0, i;
+
+       total_size = get_totalsize(mc_header);
+       data_size = get_datasize(mc_header);
+       if (data_size + MC_HEADER_SIZE > total_size) {
+               printk(KERN_ERR "microcode: error! "
+                       "Bad data size in microcode data file\n");
+               return -EINVAL;
+       }
 
-               if (copy_from_user(&mc_header, user_buffer + cursor, MC_HEADER_SIZE)) {
-                       printk(KERN_ERR "microcode: error! Can not read user data\n");
-                       error = -EFAULT;
-                       goto out;
+       if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
+               printk(KERN_ERR "microcode: error! "
+                       "Unknown microcode update format\n");
+               return -EINVAL;
+       }
+       ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
+       if (ext_table_size) {
+               if ((ext_table_size < EXT_HEADER_SIZE)
+                || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
+                       printk(KERN_ERR "microcode: error! "
+                               "Small exttable size in microcode data file\n");
+                       return -EINVAL;
                }
-
-               total_size = get_totalsize(&mc_header);
-               if ((cursor + total_size > user_buffer_size) || (total_size < DEFAULT_UCODE_TOTALSIZE)) {
-                       printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
-                       error = -EINVAL;
-                       goto out;
+               ext_header = mc + MC_HEADER_SIZE + data_size;
+               if (ext_table_size != exttable_size(ext_header)) {
+                       printk(KERN_ERR "microcode: error! "
+                               "Bad exttable size in microcode data file\n");
+                       return -EFAULT;
                }
+               ext_sigcount = ext_header->count;
+       }
 
-               data_size = get_datasize(&mc_header);
-               if ((data_size + MC_HEADER_SIZE > total_size) || (data_size < DEFAULT_UCODE_DATASIZE)) {
-                       printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
-                       error = -EINVAL;
-                       goto out;
+       /* check extended table checksum */
+       if (ext_table_size) {
+               int ext_table_sum = 0;
+               int *ext_tablep = (int *)ext_header;
+
+               i = ext_table_size / DWSIZE;
+               while (i--)
+                       ext_table_sum += ext_tablep[i];
+               if (ext_table_sum) {
+                       printk(KERN_WARNING "microcode: aborting, "
+                               "bad extended signature table checksum\n");
+                       return -EINVAL;
                }
+       }
 
-               if (mc_header.ldrver != 1 || mc_header.hdrver != 1) {
-                       printk(KERN_ERR "microcode: error! Unknown microcode update format\n");
-                       error = -EINVAL;
-                       goto out;
+       /* calculate the checksum */
+       orig_sum = 0;
+       i = (MC_HEADER_SIZE + data_size) / DWSIZE;
+       while (i--)
+               orig_sum += ((int *)mc)[i];
+       if (orig_sum) {
+               printk(KERN_ERR "microcode: aborting, bad checksum\n");
+               return -EINVAL;
+       }
+       if (!ext_table_size)
+               return 0;
+       /* check extended signature checksum */
+       for (i = 0; i < ext_sigcount; i++) {
+               ext_sig = (struct extended_signature *)((void *)ext_header
+                       + EXT_HEADER_SIZE + EXT_SIGNATURE_SIZE * i);
+               sum = orig_sum
+                       - (mc_header->sig + mc_header->pf + mc_header->cksum)
+                       + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
+               if (sum) {
+                       printk(KERN_ERR "microcode: aborting, bad checksum\n");
+                       return -EINVAL;
                }
+       }
+       return 0;
+}
 
-               for_each_online_cpu(cpu_num) {
-                       struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-
-                       if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf))
-                               mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum);
-               }
+/*
+ * return 0 - no update found
+ * return 1 - found update
+ * return < 0 - error
+ */
+static int get_maching_microcode(void *mc, int cpu)
+{
+       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+       microcode_header_t *mc_header = mc;
+       struct extended_sigtable *ext_header;
+       unsigned long total_size = get_totalsize(mc_header);
+       int ext_sigcount, i;
+       struct extended_signature *ext_sig;
+       void *new_mc;
+
+       if (microcode_update_match(cpu, mc_header,
+                       mc_header->sig, mc_header->pf))
+               goto find;
+
+       if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
+               return 0;
+
+       ext_header = (struct extended_sigtable *)(mc +
+                       get_datasize(mc_header) + MC_HEADER_SIZE);
+       ext_sigcount = ext_header->count;
+       ext_sig = (struct extended_signature *)((void *)ext_header
+                       + EXT_HEADER_SIZE);
+       for (i = 0; i < ext_sigcount; i++) {
+               if (microcode_update_match(cpu, mc_header,
+                               ext_sig->sig, ext_sig->pf))
+                       goto find;
+               ext_sig++;
+       }
+       return 0;
+find:
+       pr_debug("microcode: CPU %d found a matching microcode update with"
+               " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev);
+       new_mc = vmalloc(total_size);
+       if (!new_mc) {
+               printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+               return -ENOMEM;
+       }
 
-               ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
-               if (ext_table_size) {
-                       struct extended_sigtable ext_header;
-                       struct extended_signature ext_sig;
-                       int ext_sigcount;
+       /* free previous update file */
+       vfree(uci->mc);
 
-                       if ((ext_table_size < EXT_HEADER_SIZE) 
-                                       || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
-                               printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
-                               error = -EINVAL;
-                               goto out;
-                       }
-                       if (copy_from_user(&ext_header, user_buffer + cursor 
-                                       + MC_HEADER_SIZE + data_size, EXT_HEADER_SIZE)) {
-                               printk(KERN_ERR "microcode: error! Can not read user data\n");
-                               error = -EFAULT;
-                               goto out;
-                       }
-                       if (ext_table_size != exttable_size(&ext_header)) {
-                               printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
-                               error = -EFAULT;
-                               goto out;
-                       }
-
-                       ext_sigcount = ext_header.count;
-                       
-                       for (i = 0; i < ext_sigcount; i++) {
-                               if (copy_from_user(&ext_sig, user_buffer + cursor + MC_HEADER_SIZE + data_size + EXT_HEADER_SIZE 
-                                               + EXT_SIGNATURE_SIZE * i, EXT_SIGNATURE_SIZE)) {
-                                       printk(KERN_ERR "microcode: error! Can not read user data\n");
-                                       error = -EFAULT;
-                                       goto out;
-                               }
-                               for_each_online_cpu(cpu_num) {
-                                       struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-
-                                       if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) {
-                                               mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum);
-                                       }
-                               }
-                       }
-               }
-               /* now check if any cpu has matched */
-               allocated_flag = 0;
-               sum = 0;
-               for_each_online_cpu(cpu_num) {
-                       if (ucode_cpu_info[cpu_num].err == MC_MARKED) { 
-                               struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
-                               if (!allocated_flag) {
-                                       allocated_flag = 1;
-                                       newmc = vmalloc(total_size);
-                                       if (!newmc) {
-                                               printk(KERN_ERR "microcode: error! Can not allocate memory\n");
-                                               error = -ENOMEM;
-                                               goto out;
-                                       }
-                                       if (copy_from_user(newmc + MC_HEADER_SIZE, 
-                                                               user_buffer + cursor + MC_HEADER_SIZE, 
-                                                               total_size - MC_HEADER_SIZE)) {
-                                               printk(KERN_ERR "microcode: error! Can not read user data\n");
-                                               vfree(newmc);
-                                               error = -EFAULT;
-                                               goto out;
-                                       }
-                                       memcpy(newmc, &mc_header, MC_HEADER_SIZE);
-                                       /* check extended table checksum */
-                                       if (ext_table_size) {
-                                               int ext_table_sum = 0;
-                                               int * ext_tablep = (((void *) newmc) + MC_HEADER_SIZE + data_size);
-                                               i = ext_table_size / DWSIZE;
-                                               while (i--) ext_table_sum += ext_tablep[i];
-                                               if (ext_table_sum) {
-                                                       printk(KERN_WARNING "microcode: aborting, bad extended signature table checksum\n");
-                                                       vfree(newmc);
-                                                       error = -EINVAL;
-                                                       goto out;
-                                               }
-                                       }
-
-                                       /* calculate the checksum */
-                                       i = (MC_HEADER_SIZE + data_size) / DWSIZE;
-                                       while (i--) sum += ((int *)newmc)[i];
-                                       sum -= (mc_header.sig + mc_header.pf + mc_header.cksum);
-                               }
-                               ucode_cpu_info[cpu_num].mc = newmc;
-                               ucode_cpu_info[cpu_num].err = MC_ALLOCATED; /* mc updated */
-                               if (sum + uci->sig + uci->pf + uci->cksum != 0) {
-                                       printk(KERN_ERR "microcode: CPU%d aborting, bad checksum\n", cpu_num);
-                                       error = -EINVAL;
-                                       goto out;
-                               }
-                       }
-               }
-               cursor += total_size; /* goto the next update patch */
-       } /* end of while */
-out:
-       return error;
+       memcpy(new_mc, mc, total_size);
+       uci->mc = new_mc;
+       return 1;
 }
 
-static void do_update_one (void * unused)
+static void apply_microcode(int cpu)
 {
        unsigned long flags;
        unsigned int val[2];
-       int cpu_num = smp_processor_id();
+       int cpu_num = raw_smp_processor_id();
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
 
-       if (uci->mc == NULL) {
-               if (verbose) {
-                       if (uci->err == MC_SUCCESS)
-                               printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n",
-                                       cpu_num, uci->rev);
-                       else
-                               printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num);
-               }
+       /* We should bind the task to the CPU */
+       BUG_ON(cpu_num != cpu);
+
+       if (uci->mc == NULL)
                return;
-       }
 
        /* serialize access to the physical write to MSR 0x79 */
        spin_lock_irqsave(&microcode_update_lock, flags);          
@@ -408,68 +335,107 @@ static void do_update_one (void * unused)
        /* get the current revision from MSR 0x8B */
        rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
 
-       /* notify the caller of success on this cpu */
-       uci->err = MC_SUCCESS;
        spin_unlock_irqrestore(&microcode_update_lock, flags);
-       printk(KERN_INFO "microcode: CPU%d updated from revision "
+       if (val[1] != uci->mc->hdr.rev) {
+               printk(KERN_ERR "microcode: CPU%d updated from revision "
+                       "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
+               return;
+       }
+       pr_debug("microcode: CPU%d updated from revision "
               "0x%x to 0x%x, date = %08x \n", 
               cpu_num, uci->rev, val[1], uci->mc->hdr.date);
-       return;
+       uci->rev = val[1];
 }
 
-static int do_microcode_update (void)
-{
-       int i, error;
+#ifdef CONFIG_MICROCODE_OLD_INTERFACE
+static void __user *user_buffer;       /* user area microcode data buffer */
+static unsigned int user_buffer_size;  /* it's size */
 
-       if (on_each_cpu(collect_cpu_info, NULL, 1, 1) != 0) {
-               printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
-               error = -EIO;
-               goto out;
+static long get_next_ucode(void **mc, long offset)
+{
+       microcode_header_t mc_header;
+       unsigned long total_size;
+
+       /* No more data */
+       if (offset >= user_buffer_size)
+               return 0;
+       if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
+               printk(KERN_ERR "microcode: error! Can not read user data\n");
+               return -EFAULT;
        }
-
-       if ((error = find_matching_ucodes())) {
-               printk(KERN_ERR "microcode: Error in the microcode data\n");
-               goto out_free;
+       total_size = get_totalsize(&mc_header);
+       if (offset + total_size > user_buffer_size) {
+               printk(KERN_ERR "microcode: error! Bad total size in microcode "
+                               "data file\n");
+               return -EINVAL;
        }
-
-       if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) {
-               printk(KERN_ERR "microcode: Error! Could not run on all processors\n");
-               error = -EIO;
+       *mc = vmalloc(total_size);
+       if (!*mc)
+               return -ENOMEM;
+       if (copy_from_user(*mc, user_buffer + offset, total_size)) {
+               printk(KERN_ERR "microcode: error! Can not read user data\n");
+               vfree(*mc);
+               return -EFAULT;
        }
+       return offset + total_size;
+}
+
+static int do_microcode_update (void)
+{
+       long cursor = 0;
+       int error = 0;
+       void *new_mc;
+       int cpu;
+       cpumask_t old;
+
+       old = current->cpus_allowed;
 
-out_free:
-       for_each_online_cpu(i) {
-               if (ucode_cpu_info[i].mc) {
-                       int j;
-                       void *tmp = ucode_cpu_info[i].mc;
-                       vfree(tmp);
-                       for_each_online_cpu(j) {
-                               if (ucode_cpu_info[j].mc == tmp)
-                                       ucode_cpu_info[j].mc = NULL;
-                       }
+       while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) {
+               error = microcode_sanity_check(new_mc);
+               if (error)
+                       goto out;
+               /*
+                * It's possible the data file has multiple matching ucode,
+                * lets keep searching till the latest version
+                */
+               for_each_online_cpu(cpu) {
+                       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+                       if (!uci->valid)
+                               continue;
+                       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+                       error = get_maching_microcode(new_mc, cpu);
+                       if (error < 0)
+                               goto out;
+                       if (error == 1)
+                               apply_microcode(cpu);
                }
-               if (ucode_cpu_info[i].err == MC_IGNORED && verbose)
-                       printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision"
-                              " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev);
+               vfree(new_mc);
        }
 out:
+       if (cursor > 0)
+               vfree(new_mc);
+       if (cursor < 0)
+               error = cursor;
+       set_cpus_allowed(current, old);
        return error;
 }
 
+static int microcode_open (struct inode *unused1, struct file *unused2)
+{
+       return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
+}
+
 static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
 {
        ssize_t ret;
 
-       if (len < DEFAULT_UCODE_TOTALSIZE) {
-               printk(KERN_ERR "microcode: not enough data\n"); 
-               return -EINVAL;
-       }
-
        if ((len >> PAGE_SHIFT) > num_physpages) {
                printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages);
                return -EINVAL;
        }
 
+       lock_cpu_hotplug();
        mutex_lock(&microcode_mutex);
 
        user_buffer = (void __user *) buf;
@@ -480,6 +446,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
                ret = (ssize_t)len;
 
        mutex_unlock(&microcode_mutex);
+       unlock_cpu_hotplug();
 
        return ret;
 }
@@ -496,7 +463,7 @@ static struct miscdevice microcode_dev = {
        .fops           = &microcode_fops,
 };
 
-static int __init microcode_init (void)
+static int __init microcode_dev_init (void)
 {
        int error;
 
@@ -508,6 +475,280 @@ static int __init microcode_init (void)
                return error;
        }
 
+       return 0;
+}
+
+static void __exit microcode_dev_exit (void)
+{
+       misc_deregister(&microcode_dev);
+}
+
+MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
+#else
+#define microcode_dev_init() 0
+#define microcode_dev_exit() do { } while(0)
+#endif
+
+static long get_next_ucode_from_buffer(void **mc, void *buf,
+       unsigned long size, long offset)
+{
+       microcode_header_t *mc_header;
+       unsigned long total_size;
+
+       /* No more data */
+       if (offset >= size)
+               return 0;
+       mc_header = (microcode_header_t *)(buf + offset);
+       total_size = get_totalsize(mc_header);
+
+       if (offset + total_size > size) {
+               printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
+               return -EINVAL;
+       }
+
+       *mc = vmalloc(total_size);
+       if (!*mc) {
+               printk(KERN_ERR "microcode: error! Can not allocate memory\n");
+               return -ENOMEM;
+       }
+       memcpy(*mc, buf + offset, total_size);
+       return offset + total_size;
+}
+
+/* fake device for request_firmware */
+static struct platform_device *microcode_pdev;
+
+static int cpu_request_microcode(int cpu)
+{
+       char name[30];
+       struct cpuinfo_x86 *c = cpu_data + cpu;
+       const struct firmware *firmware;
+       void *buf;
+       unsigned long size;
+       long offset = 0;
+       int error;
+       void *mc;
+
+       /* We should bind the task to the CPU */
+       BUG_ON(cpu != raw_smp_processor_id());
+       sprintf(name,"intel-ucode/%02x-%02x-%02x",
+               c->x86, c->x86_model, c->x86_mask);
+       error = request_firmware(&firmware, name, &microcode_pdev->dev);
+       if (error) {
+               pr_debug("ucode data file %s load failed\n", name);
+               return error;
+       }
+       buf = (void *)firmware->data;
+       size = firmware->size;
+       while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
+                       > 0) {
+               error = microcode_sanity_check(mc);
+               if (error)
+                       break;
+               error = get_maching_microcode(mc, cpu);
+               if (error < 0)
+                       break;
+               /*
+                * It's possible the data file has multiple matching ucode,
+                * lets keep searching till the latest version
+                */
+               if (error == 1) {
+                       apply_microcode(cpu);
+                       error = 0;
+               }
+               vfree(mc);
+       }
+       if (offset > 0)
+               vfree(mc);
+       if (offset < 0)
+               error = offset;
+       release_firmware(firmware);
+
+       return error;
+}
+
+static void microcode_init_cpu(int cpu)
+{
+       cpumask_t old;
+       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+       old = current->cpus_allowed;
+
+       set_cpus_allowed(current, cpumask_of_cpu(cpu));
+       mutex_lock(&microcode_mutex);
+       collect_cpu_info(cpu);
+       if (uci->valid)
+               cpu_request_microcode(cpu);
+       mutex_unlock(&microcode_mutex);
+       set_cpus_allowed(current, old);
+}
+
+static void microcode_fini_cpu(int cpu)
+{
+       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+       mutex_lock(&microcode_mutex);
+       uci->valid = 0;
+       vfree(uci->mc);
+       uci->mc = NULL;
+       mutex_unlock(&microcode_mutex);
+}
+
+static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
+{
+       struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+       char *end;
+       unsigned long val = simple_strtoul(buf, &end, 0);
+       int err = 0;
+       int cpu = dev->id;
+
+       if (end == buf)
+               return -EINVAL;
+       if (val == 1) {
+               cpumask_t old;
+
+               old = current->cpus_allowed;
+
+               lock_cpu_hotplug();
+               set_cpus_allowed(current, cpumask_of_cpu(cpu));
+
+               mutex_lock(&microcode_mutex);
+               if (uci->valid)
+                       err = cpu_request_microcode(cpu);
+               mutex_unlock(&microcode_mutex);
+               unlock_cpu_hotplug();
+               set_cpus_allowed(current, old);
+       }
+       if (err)
+               return err;
+       return sz;
+}
+
+static ssize_t version_show(struct sys_device *dev, char *buf)
+{
+       struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+
+       return sprintf(buf, "0x%x\n", uci->rev);
+}
+
+static ssize_t pf_show(struct sys_device *dev, char *buf)
+{
+       struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
+
+       return sprintf(buf, "0x%x\n", uci->pf);
+}
+
+static SYSDEV_ATTR(reload, 0200, NULL, reload_store);
+static SYSDEV_ATTR(version, 0400, version_show, NULL);
+static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL);
+
+static struct attribute *mc_default_attrs[] = {
+       &attr_reload.attr,
+       &attr_version.attr,
+       &attr_processor_flags.attr,
+       NULL
+};
+
+static struct attribute_group mc_attr_group = {
+       .attrs = mc_default_attrs,
+       .name = "microcode",
+};
+
+static int mc_sysdev_add(struct sys_device *sys_dev)
+{
+       int cpu = sys_dev->id;
+       struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+
+       if (!cpu_online(cpu))
+               return 0;
+       pr_debug("Microcode:CPU %d added\n", cpu);
+       memset(uci, 0, sizeof(*uci));
+       sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
+
+       microcode_init_cpu(cpu);
+       return 0;
+}
+
+static int mc_sysdev_remove(struct sys_device *sys_dev)
+{
+       int cpu = sys_dev->id;
+
+       if (!cpu_online(cpu))
+               return 0;
+       pr_debug("Microcode:CPU %d removed\n", cpu);
+       microcode_fini_cpu(cpu);
+       sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
+       return 0;
+}
+
+static int mc_sysdev_resume(struct sys_device *dev)
+{
+       int cpu = dev->id;
+
+       if (!cpu_online(cpu))
+               return 0;
+       pr_debug("Microcode:CPU %d resumed\n", cpu);
+       /* only CPU 0 will apply ucode here */
+       apply_microcode(0);
+       return 0;
+}
+
+static struct sysdev_driver mc_sysdev_driver = {
+       .add = mc_sysdev_add,
+       .remove = mc_sysdev_remove,
+       .resume = mc_sysdev_resume,
+};
+
+#ifdef CONFIG_HOTPLUG_CPU
+static __cpuinit int
+mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (unsigned long)hcpu;
+       struct sys_device *sys_dev;
+
+       sys_dev = get_cpu_sysdev(cpu);
+       switch (action) {
+       case CPU_ONLINE:
+       case CPU_DOWN_FAILED:
+               mc_sysdev_add(sys_dev);
+               break;
+       case CPU_DOWN_PREPARE:
+               mc_sysdev_remove(sys_dev);
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block mc_cpu_notifier = {
+       .notifier_call = mc_cpu_callback,
+};
+#endif
+
+static int __init microcode_init (void)
+{
+       int error;
+
+       error = microcode_dev_init();
+       if (error)
+               return error;
+       microcode_pdev = platform_device_register_simple("microcode", -1,
+                                                        NULL, 0);
+       if (IS_ERR(microcode_pdev)) {
+               microcode_dev_exit();
+               return PTR_ERR(microcode_pdev);
+       }
+
+       lock_cpu_hotplug();
+       error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
+       unlock_cpu_hotplug();
+       if (error) {
+               microcode_dev_exit();
+               platform_device_unregister(microcode_pdev);
+               return error;
+       }
+
+       register_hotcpu_notifier(&mc_cpu_notifier);
+
        printk(KERN_INFO 
                "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
        return 0;
@@ -515,9 +756,16 @@ static int __init microcode_init (void)
 
 static void __exit microcode_exit (void)
 {
-       misc_deregister(&microcode_dev);
+       microcode_dev_exit();
+
+       unregister_hotcpu_notifier(&mc_cpu_notifier);
+
+       lock_cpu_hotplug();
+       sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
+       unlock_cpu_hotplug();
+
+       platform_device_unregister(microcode_pdev);
 }
 
 module_init(microcode_init)
 module_exit(microcode_exit)
-MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
index a70b5fa0ef06fd3cf165349959d52f25fe151fed..442aaf8c77ebf593fd249f9f4e69db8df3070be9 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/io_apic.h>
 
 #include <mach_apic.h>
+#include <mach_apicdef.h>
 #include <mach_mpparse.h>
 #include <bios_ebda.h>
 
@@ -68,7 +69,7 @@ unsigned int def_to_bigsmp = 0;
 /* Processor that is doing the boot up */
 unsigned int boot_cpu_physical_apicid = -1U;
 /* Internal processor count */
-static unsigned int __devinitdata num_processors;
+unsigned int __cpuinitdata num_processors;
 
 /* Bitmask of physically existing CPUs */
 physid_mask_t phys_cpu_present_map;
@@ -228,12 +229,14 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
 
        mpc_oem_bus_info(m, str, translation_table[mpc_record]);
 
+#if MAX_MP_BUSSES < 256
        if (m->mpc_busid >= MAX_MP_BUSSES) {
                printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
                        " is too large, max. supported is %d\n",
                        m->mpc_busid, str, MAX_MP_BUSSES - 1);
                return;
        }
+#endif
 
        if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
                mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
@@ -293,19 +296,6 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
                        m->mpc_irqtype, m->mpc_irqflag & 3,
                        (m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
                        m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
-       /*
-        * Well it seems all SMP boards in existence
-        * use ExtINT/LVT1 == LINT0 and
-        * NMI/LVT2 == LINT1 - the following check
-        * will show us if this assumptions is false.
-        * Until then we do not have to add baggage.
-        */
-       if ((m->mpc_irqtype == mp_ExtINT) &&
-               (m->mpc_destapiclint != 0))
-                       BUG();
-       if ((m->mpc_irqtype == mp_NMI) &&
-               (m->mpc_destapiclint != 1))
-                       BUG();
 }
 
 #ifdef CONFIG_X86_NUMAQ
@@ -822,8 +812,7 @@ int es7000_plat;
 
 #ifdef CONFIG_ACPI
 
-void __init mp_register_lapic_address (
-       u64                     address)
+void __init mp_register_lapic_address(u64 address)
 {
        mp_lapic_addr = (unsigned long) address;
 
@@ -835,13 +824,10 @@ void __init mp_register_lapic_address (
        Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
 }
 
-
-void __devinit mp_register_lapic (
-       u8                      id, 
-       u8                      enabled)
+void __devinit mp_register_lapic (u8 id, u8 enabled)
 {
        struct mpc_config_processor processor;
-       int                     boot_cpu = 0;
+       int boot_cpu = 0;
        
        if (MAX_APICS - id <= 0) {
                printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
@@ -878,11 +864,9 @@ static struct mp_ioapic_routing {
        u32                     pin_programmed[4];
 } mp_ioapic_routing[MAX_IO_APICS];
 
-
-static int mp_find_ioapic (
-       int                     gsi)
+static int mp_find_ioapic (int gsi)
 {
-       int                     i = 0;
+       int i = 0;
 
        /* Find the IOAPIC that manages this GSI. */
        for (i = 0; i < nr_ioapics; i++) {
@@ -895,15 +879,11 @@ static int mp_find_ioapic (
 
        return -1;
 }
-       
 
-void __init mp_register_ioapic (
-       u8                      id, 
-       u32                     address,
-       u32                     gsi_base)
+void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
 {
-       int                     idx = 0;
-       int                     tmpid;
+       int idx = 0;
+       int tmpid;
 
        if (nr_ioapics >= MAX_IO_APICS) {
                printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
@@ -949,16 +929,10 @@ void __init mp_register_ioapic (
                mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
                mp_ioapic_routing[idx].gsi_base,
                mp_ioapic_routing[idx].gsi_end);
-
-       return;
 }
 
-
-void __init mp_override_legacy_irq (
-       u8                      bus_irq,
-       u8                      polarity, 
-       u8                      trigger, 
-       u32                     gsi)
+void __init
+mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
 {
        struct mpc_config_intsrc intsrc;
        int                     ioapic = -1;
@@ -996,15 +970,13 @@ void __init mp_override_legacy_irq (
        mp_irqs[mp_irq_entries] = intsrc;
        if (++mp_irq_entries == MAX_IRQ_SOURCES)
                panic("Max # of irq sources exceeded!\n");
-
-       return;
 }
 
 void __init mp_config_acpi_legacy_irqs (void)
 {
        struct mpc_config_intsrc intsrc;
-       int                     i = 0;
-       int                     ioapic = -1;
+       int i = 0;
+       int ioapic = -1;
 
        /* 
         * Fabricate the legacy ISA bus (bus #31).
@@ -1073,12 +1045,12 @@ void __init mp_config_acpi_legacy_irqs (void)
 
 #define MAX_GSI_NUM    4096
 
-int mp_register_gsi (u32 gsi, int triggering, int polarity)
+int mp_register_gsi(u32 gsi, int triggering, int polarity)
 {
-       int                     ioapic = -1;
-       int                     ioapic_pin = 0;
-       int                     idx, bit = 0;
-       static int              pci_irq = 16;
+       int ioapic = -1;
+       int ioapic_pin = 0;
+       int idx, bit = 0;
+       static int pci_irq = 16;
        /*
         * Mapping between Global System Interrups, which
         * represent all possible interrupts, and IRQs
index acb351478e42b9f5e4693de4ca6d5786d2ed8f37..dbda706fdd14e9e704ee1ab846b3ba361ddeaaf3 100644 (file)
 #include <linux/sysdev.h>
 #include <linux/sysctl.h>
 #include <linux/percpu.h>
+#include <linux/dmi.h>
+#include <linux/kprobes.h>
 
 #include <asm/smp.h>
 #include <asm/nmi.h>
+#include <asm/kdebug.h>
 #include <asm/intel_arch_perfmon.h>
 
 #include "mach_traps.h"
 
-unsigned int nmi_watchdog = NMI_NONE;
-extern int unknown_nmi_panic;
-static unsigned int nmi_hz = HZ;
-static unsigned int nmi_perfctr_msr;   /* the MSR to reset in NMI handler */
-static unsigned int nmi_p4_cccr_val;
-extern void show_registers(struct pt_regs *regs);
+/* perfctr_nmi_owner tracks the ownership of the perfctr registers:
+ * evtsel_nmi_owner tracks the ownership of the event selection
+ * - different performance counters/ event selection may be reserved for
+ *   different subsystems this reservation system just tries to coordinate
+ *   things a little
+ */
+static DEFINE_PER_CPU(unsigned long, perfctr_nmi_owner);
+static DEFINE_PER_CPU(unsigned long, evntsel_nmi_owner[3]);
 
-/*
- * lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
- * - it may be reserved by some other driver, or not
- * - when not reserved by some other driver, it may be used for
- *   the NMI watchdog, or not
- *
- * This is maintained separately from nmi_active because the NMI
- * watchdog may also be driven from the I/O APIC timer.
+/* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's
+ * offset from MSR_P4_BSU_ESCR0.  It will be the max for all platforms (for now)
  */
-static DEFINE_SPINLOCK(lapic_nmi_owner_lock);
-static unsigned int lapic_nmi_owner;
-#define LAPIC_NMI_WATCHDOG     (1<<0)
-#define LAPIC_NMI_RESERVED     (1<<1)
+#define NMI_MAX_COUNTER_BITS 66
 
 /* nmi_active:
- * +1: the lapic NMI watchdog is active, but can be disabled
- *  0: the lapic NMI watchdog has not been set up, and cannot
+ * >0: the lapic NMI watchdog is active, but can be disabled
+ * <0: the lapic NMI watchdog has not been set up, and cannot
  *     be enabled
- * -1: the lapic NMI watchdog is disabled, but can be enabled
+ *  0: the lapic NMI watchdog is disabled, but can be enabled
  */
-int nmi_active;
+atomic_t nmi_active = ATOMIC_INIT(0);          /* oprofile uses this */
 
-#define K7_EVNTSEL_ENABLE      (1 << 22)
-#define K7_EVNTSEL_INT         (1 << 20)
-#define K7_EVNTSEL_OS          (1 << 17)
-#define K7_EVNTSEL_USR         (1 << 16)
-#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING   0x76
-#define K7_NMI_EVENT           K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
+unsigned int nmi_watchdog = NMI_DEFAULT;
+static unsigned int nmi_hz = HZ;
 
-#define P6_EVNTSEL0_ENABLE     (1 << 22)
-#define P6_EVNTSEL_INT         (1 << 20)
-#define P6_EVNTSEL_OS          (1 << 17)
-#define P6_EVNTSEL_USR         (1 << 16)
-#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
-#define P6_NMI_EVENT           P6_EVENT_CPU_CLOCKS_NOT_HALTED
+struct nmi_watchdog_ctlblk {
+       int enabled;
+       u64 check_bit;
+       unsigned int cccr_msr;
+       unsigned int perfctr_msr;  /* the MSR to reset in NMI handler */
+       unsigned int evntsel_msr;  /* the MSR to select the events to handle */
+};
+static DEFINE_PER_CPU(struct nmi_watchdog_ctlblk, nmi_watchdog_ctlblk);
 
-#define MSR_P4_MISC_ENABLE     0x1A0
-#define MSR_P4_MISC_ENABLE_PERF_AVAIL  (1<<7)
-#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL        (1<<12)
-#define MSR_P4_PERFCTR0                0x300
-#define MSR_P4_CCCR0           0x360
-#define P4_ESCR_EVENT_SELECT(N)        ((N)<<25)
-#define P4_ESCR_OS             (1<<3)
-#define P4_ESCR_USR            (1<<2)
-#define P4_CCCR_OVF_PMI0       (1<<26)
-#define P4_CCCR_OVF_PMI1       (1<<27)
-#define P4_CCCR_THRESHOLD(N)   ((N)<<20)
-#define P4_CCCR_COMPLEMENT     (1<<19)
-#define P4_CCCR_COMPARE                (1<<18)
-#define P4_CCCR_REQUIRED       (3<<16)
-#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
-#define P4_CCCR_ENABLE         (1<<12)
-/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
-   CRU_ESCR0 (with any non-null event selector) through a complemented
-   max threshold. [IA32-Vol3, Section 14.9.9] */
-#define MSR_P4_IQ_COUNTER0     0x30C
-#define P4_NMI_CRU_ESCR0       (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
-#define P4_NMI_IQ_CCCR0        \
-       (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|     \
-        P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
+/* local prototypes */
+static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu);
 
-#define ARCH_PERFMON_NMI_EVENT_SEL     ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
-#define ARCH_PERFMON_NMI_EVENT_UMASK   ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+extern void show_registers(struct pt_regs *regs);
+extern int unknown_nmi_panic;
+
+/* converts an msr to an appropriate reservation bit */
+static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
+{
+       /* returns the bit offset of the performance counter register */
+       switch (boot_cpu_data.x86_vendor) {
+       case X86_VENDOR_AMD:
+               return (msr - MSR_K7_PERFCTR0);
+       case X86_VENDOR_INTEL:
+               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+                       return (msr - MSR_ARCH_PERFMON_PERFCTR0);
+
+               switch (boot_cpu_data.x86) {
+               case 6:
+                       return (msr - MSR_P6_PERFCTR0);
+               case 15:
+                       return (msr - MSR_P4_BPU_PERFCTR0);
+               }
+       }
+       return 0;
+}
+
+/* converts an msr to an appropriate reservation bit */
+static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
+{
+       /* returns the bit offset of the event selection register */
+       switch (boot_cpu_data.x86_vendor) {
+       case X86_VENDOR_AMD:
+               return (msr - MSR_K7_EVNTSEL0);
+       case X86_VENDOR_INTEL:
+               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+                       return (msr - MSR_ARCH_PERFMON_EVENTSEL0);
+
+               switch (boot_cpu_data.x86) {
+               case 6:
+                       return (msr - MSR_P6_EVNTSEL0);
+               case 15:
+                       return (msr - MSR_P4_BSU_ESCR0);
+               }
+       }
+       return 0;
+}
+
+/* checks for a bit availability (hack for oprofile) */
+int avail_to_resrv_perfctr_nmi_bit(unsigned int counter)
+{
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner)));
+}
+
+/* checks the an msr for availability */
+int avail_to_resrv_perfctr_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_perfctr_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner)));
+}
+
+int reserve_perfctr_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_perfctr_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       if (!test_and_set_bit(counter, &__get_cpu_var(perfctr_nmi_owner)))
+               return 1;
+       return 0;
+}
+
+void release_perfctr_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_perfctr_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       clear_bit(counter, &__get_cpu_var(perfctr_nmi_owner));
+}
+
+int reserve_evntsel_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_evntsel_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       if (!test_and_set_bit(counter, &__get_cpu_var(evntsel_nmi_owner)[0]))
+               return 1;
+       return 0;
+}
+
+void release_evntsel_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_evntsel_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       clear_bit(counter, &__get_cpu_var(evntsel_nmi_owner)[0]);
+}
+
+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));
+       case X86_VENDOR_INTEL:
+               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+                       return 1;
+               else
+                       return ((boot_cpu_data.x86 == 15) || (boot_cpu_data.x86 == 6));
+       }
+       return 0;
+}
 
 #ifdef CONFIG_SMP
 /* The performance counters used by NMI_LOCAL_APIC don't trigger when
@@ -125,7 +216,18 @@ static int __init check_nmi_watchdog(void)
        unsigned int *prev_nmi_count;
        int cpu;
 
-       if (nmi_watchdog == NMI_NONE)
+       /* Enable NMI watchdog for newer systems.
+           Actually it should be safe for most systems before 2004 too except
+          for some IBM systems that corrupt registers when NMI happens
+          during SMM. Unfortunately we don't have more exact information
+          on these and use this coarse check. */
+       if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004)
+               nmi_watchdog = NMI_LOCAL_APIC;
+
+       if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT))
+               return 0;
+
+       if (!atomic_read(&nmi_active))
                return 0;
 
        prev_nmi_count = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
@@ -149,25 +251,45 @@ static int __init check_nmi_watchdog(void)
                if (!cpu_isset(cpu, cpu_callin_map))
                        continue;
 #endif
+               if (!per_cpu(nmi_watchdog_ctlblk, cpu).enabled)
+                       continue;
                if (nmi_count(cpu) - prev_nmi_count[cpu] <= 5) {
-                       endflag = 1;
                        printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
                                cpu,
                                prev_nmi_count[cpu],
                                nmi_count(cpu));
-                       nmi_active = 0;
-                       lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
-                       kfree(prev_nmi_count);
-                       return -1;
+                       per_cpu(nmi_watchdog_ctlblk, cpu).enabled = 0;
+                       atomic_dec(&nmi_active);
                }
        }
+       if (!atomic_read(&nmi_active)) {
+               kfree(prev_nmi_count);
+               atomic_set(&nmi_active, -1);
+               return -1;
+       }
        endflag = 1;
        printk("OK.\n");
 
        /* now that we know it works we can reduce NMI frequency to
           something more reasonable; makes a difference in some configs */
-       if (nmi_watchdog == NMI_LOCAL_APIC)
+       if (nmi_watchdog == NMI_LOCAL_APIC) {
+               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;
+               }
+       }
 
        kfree(prev_nmi_count);
        return 0;
@@ -181,124 +303,70 @@ static int __init setup_nmi_watchdog(char *str)
 
        get_option(&str, &nmi);
 
-       if (nmi >= NMI_INVALID)
+       if ((nmi >= NMI_INVALID) || (nmi < NMI_NONE))
                return 0;
-       if (nmi == NMI_NONE)
-               nmi_watchdog = nmi;
        /*
         * If any other x86 CPU has a local APIC, then
         * please test the NMI stuff there and send me the
         * missing bits. Right now Intel P6/P4 and AMD K7 only.
         */
-       if ((nmi == NMI_LOCAL_APIC) &&
-                       (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
-                       (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15))
-               nmi_watchdog = nmi;
-       if ((nmi == NMI_LOCAL_APIC) &&
-                       (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
-                       (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15))
-               nmi_watchdog = nmi;
-       /*
-        * We can enable the IO-APIC watchdog
-        * unconditionally.
-        */
-       if (nmi == NMI_IO_APIC) {
-               nmi_active = 1;
-               nmi_watchdog = nmi;
-       }
+       if ((nmi == NMI_LOCAL_APIC) && (nmi_known_cpu() == 0))
+               return 0;  /* no lapic support */
+       nmi_watchdog = nmi;
        return 1;
 }
 
 __setup("nmi_watchdog=", setup_nmi_watchdog);
 
-static void disable_intel_arch_watchdog(void);
-
 static void disable_lapic_nmi_watchdog(void)
 {
-       if (nmi_active <= 0)
+       BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
+
+       if (atomic_read(&nmi_active) <= 0)
                return;
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_AMD:
-               wrmsr(MSR_K7_EVNTSEL0, 0, 0);
-               break;
-       case X86_VENDOR_INTEL:
-               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
-                       disable_intel_arch_watchdog();
-                       break;
-               }
-               switch (boot_cpu_data.x86) {
-               case 6:
-                       if (boot_cpu_data.x86_model > 0xd)
-                               break;
 
-                       wrmsr(MSR_P6_EVNTSEL0, 0, 0);
-                       break;
-               case 15:
-                       if (boot_cpu_data.x86_model > 0x4)
-                               break;
+       on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
 
-                       wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
-                       wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
-                       break;
-               }
-               break;
-       }
-       nmi_active = -1;
-       /* tell do_nmi() and others that we're not active any more */
-       nmi_watchdog = 0;
+       BUG_ON(atomic_read(&nmi_active) != 0);
 }
 
 static void enable_lapic_nmi_watchdog(void)
 {
-       if (nmi_active < 0) {
-               nmi_watchdog = NMI_LOCAL_APIC;
-               setup_apic_nmi_watchdog();
-       }
-}
+       BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
 
-int reserve_lapic_nmi(void)
-{
-       unsigned int old_owner;
-
-       spin_lock(&lapic_nmi_owner_lock);
-       old_owner = lapic_nmi_owner;
-       lapic_nmi_owner |= LAPIC_NMI_RESERVED;
-       spin_unlock(&lapic_nmi_owner_lock);
-       if (old_owner & LAPIC_NMI_RESERVED)
-               return -EBUSY;
-       if (old_owner & LAPIC_NMI_WATCHDOG)
-               disable_lapic_nmi_watchdog();
-       return 0;
-}
+       /* are we already enabled */
+       if (atomic_read(&nmi_active) != 0)
+               return;
 
-void release_lapic_nmi(void)
-{
-       unsigned int new_owner;
+       /* are we lapic aware */
+       if (nmi_known_cpu() <= 0)
+               return;
 
-       spin_lock(&lapic_nmi_owner_lock);
-       new_owner = lapic_nmi_owner & ~LAPIC_NMI_RESERVED;
-       lapic_nmi_owner = new_owner;
-       spin_unlock(&lapic_nmi_owner_lock);
-       if (new_owner & LAPIC_NMI_WATCHDOG)
-               enable_lapic_nmi_watchdog();
+       on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
+       touch_nmi_watchdog();
 }
 
 void disable_timer_nmi_watchdog(void)
 {
-       if ((nmi_watchdog != NMI_IO_APIC) || (nmi_active <= 0))
+       BUG_ON(nmi_watchdog != NMI_IO_APIC);
+
+       if (atomic_read(&nmi_active) <= 0)
                return;
 
-       unset_nmi_callback();
-       nmi_active = -1;
-       nmi_watchdog = NMI_NONE;
+       disable_irq(0);
+       on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
+
+       BUG_ON(atomic_read(&nmi_active) != 0);
 }
 
 void enable_timer_nmi_watchdog(void)
 {
-       if (nmi_active < 0) {
-               nmi_watchdog = NMI_IO_APIC;
+       BUG_ON(nmi_watchdog != NMI_IO_APIC);
+
+       if (atomic_read(&nmi_active) == 0) {
                touch_nmi_watchdog();
-               nmi_active = 1;
+               on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
+               enable_irq(0);
        }
 }
 
@@ -308,15 +376,20 @@ static int nmi_pm_active; /* nmi_active before suspend */
 
 static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
 {
-       nmi_pm_active = nmi_active;
-       disable_lapic_nmi_watchdog();
+       /* only CPU0 goes here, other CPUs should be offline */
+       nmi_pm_active = atomic_read(&nmi_active);
+       stop_apic_nmi_watchdog(NULL);
+       BUG_ON(atomic_read(&nmi_active) != 0);
        return 0;
 }
 
 static int lapic_nmi_resume(struct sys_device *dev)
 {
-       if (nmi_pm_active > 0)
-               enable_lapic_nmi_watchdog();
+       /* only CPU0 goes here, other CPUs should be offline */
+       if (nmi_pm_active > 0) {
+               setup_apic_nmi_watchdog(NULL);
+               touch_nmi_watchdog();
+       }
        return 0;
 }
 
@@ -336,7 +409,13 @@ static int __init init_lapic_nmi_sysfs(void)
 {
        int error;
 
-       if (nmi_active == 0 || nmi_watchdog != NMI_LOCAL_APIC)
+       /* should really be a BUG_ON but b/c this is an
+        * init call, it just doesn't work.  -dcz
+        */
+       if (nmi_watchdog != NMI_LOCAL_APIC)
+               return 0;
+
+       if ( atomic_read(&nmi_active) < 0 )
                return 0;
 
        error = sysdev_class_register(&nmi_sysclass);
@@ -354,138 +433,269 @@ late_initcall(init_lapic_nmi_sysfs);
  * Original code written by Keith Owens.
  */
 
-static void clear_msr_range(unsigned int base, unsigned int n)
-{
-       unsigned int i;
-
-       for(i = 0; i < n; ++i)
-               wrmsr(base+i, 0, 0);
-}
-
-static void write_watchdog_counter(const char *descr)
+static void write_watchdog_counter(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);
-       wrmsrl(nmi_perfctr_msr, 0 - count);
+       wrmsrl(perfctr_msr, 0 - count);
 }
 
-static void setup_k7_watchdog(void)
+/* Note that these events don't tick when the CPU idles. This means
+   the frequency varies with CPU load. */
+
+#define K7_EVNTSEL_ENABLE      (1 << 22)
+#define K7_EVNTSEL_INT         (1 << 20)
+#define K7_EVNTSEL_OS          (1 << 17)
+#define K7_EVNTSEL_USR         (1 << 16)
+#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING   0x76
+#define K7_NMI_EVENT           K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
+
+static int setup_k7_watchdog(void)
 {
+       unsigned int perfctr_msr, evntsel_msr;
        unsigned int evntsel;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       perfctr_msr = MSR_K7_PERFCTR0;
+       evntsel_msr = MSR_K7_EVNTSEL0;
+       if (!reserve_perfctr_nmi(perfctr_msr))
+               goto fail;
 
-       nmi_perfctr_msr = MSR_K7_PERFCTR0;
+       if (!reserve_evntsel_nmi(evntsel_msr))
+               goto fail1;
 
-       clear_msr_range(MSR_K7_EVNTSEL0, 4);
-       clear_msr_range(MSR_K7_PERFCTR0, 4);
+       wrmsrl(perfctr_msr, 0UL);
 
        evntsel = K7_EVNTSEL_INT
                | K7_EVNTSEL_OS
                | K7_EVNTSEL_USR
                | K7_NMI_EVENT;
 
-       wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
-       write_watchdog_counter("K7_PERFCTR0");
+       /* setup the timer */
+       wrmsr(evntsel_msr, evntsel, 0);
+       write_watchdog_counter(perfctr_msr, "K7_PERFCTR0");
        apic_write(APIC_LVTPC, APIC_DM_NMI);
        evntsel |= K7_EVNTSEL_ENABLE;
-       wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
+       wrmsr(evntsel_msr, evntsel, 0);
+
+       wd->perfctr_msr = perfctr_msr;
+       wd->evntsel_msr = evntsel_msr;
+       wd->cccr_msr = 0;  //unused
+       wd->check_bit = 1ULL<<63;
+       return 1;
+fail1:
+       release_perfctr_nmi(perfctr_msr);
+fail:
+       return 0;
+}
+
+static void stop_k7_watchdog(void)
+{
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       wrmsr(wd->evntsel_msr, 0, 0);
+
+       release_evntsel_nmi(wd->evntsel_msr);
+       release_perfctr_nmi(wd->perfctr_msr);
 }
 
-static void setup_p6_watchdog(void)
+#define P6_EVNTSEL0_ENABLE     (1 << 22)
+#define P6_EVNTSEL_INT         (1 << 20)
+#define P6_EVNTSEL_OS          (1 << 17)
+#define P6_EVNTSEL_USR         (1 << 16)
+#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
+#define P6_NMI_EVENT           P6_EVENT_CPU_CLOCKS_NOT_HALTED
+
+static int setup_p6_watchdog(void)
 {
+       unsigned int perfctr_msr, evntsel_msr;
        unsigned int evntsel;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       perfctr_msr = MSR_P6_PERFCTR0;
+       evntsel_msr = MSR_P6_EVNTSEL0;
+       if (!reserve_perfctr_nmi(perfctr_msr))
+               goto fail;
 
-       nmi_perfctr_msr = MSR_P6_PERFCTR0;
+       if (!reserve_evntsel_nmi(evntsel_msr))
+               goto fail1;
 
-       clear_msr_range(MSR_P6_EVNTSEL0, 2);
-       clear_msr_range(MSR_P6_PERFCTR0, 2);
+       wrmsrl(perfctr_msr, 0UL);
 
        evntsel = P6_EVNTSEL_INT
                | P6_EVNTSEL_OS
                | P6_EVNTSEL_USR
                | P6_NMI_EVENT;
 
-       wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
-       write_watchdog_counter("P6_PERFCTR0");
+       /* setup the timer */
+       wrmsr(evntsel_msr, evntsel, 0);
+       write_watchdog_counter(perfctr_msr, "P6_PERFCTR0");
        apic_write(APIC_LVTPC, APIC_DM_NMI);
        evntsel |= P6_EVNTSEL0_ENABLE;
-       wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
+       wrmsr(evntsel_msr, evntsel, 0);
+
+       wd->perfctr_msr = perfctr_msr;
+       wd->evntsel_msr = evntsel_msr;
+       wd->cccr_msr = 0;  //unused
+       wd->check_bit = 1ULL<<39;
+       return 1;
+fail1:
+       release_perfctr_nmi(perfctr_msr);
+fail:
+       return 0;
+}
+
+static void stop_p6_watchdog(void)
+{
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       wrmsr(wd->evntsel_msr, 0, 0);
+
+       release_evntsel_nmi(wd->evntsel_msr);
+       release_perfctr_nmi(wd->perfctr_msr);
 }
 
+/* Note that these events don't tick when the CPU idles. This means
+   the frequency varies with CPU load. */
+
+#define MSR_P4_MISC_ENABLE_PERF_AVAIL  (1<<7)
+#define P4_ESCR_EVENT_SELECT(N)        ((N)<<25)
+#define P4_ESCR_OS             (1<<3)
+#define P4_ESCR_USR            (1<<2)
+#define P4_CCCR_OVF_PMI0       (1<<26)
+#define P4_CCCR_OVF_PMI1       (1<<27)
+#define P4_CCCR_THRESHOLD(N)   ((N)<<20)
+#define P4_CCCR_COMPLEMENT     (1<<19)
+#define P4_CCCR_COMPARE                (1<<18)
+#define P4_CCCR_REQUIRED       (3<<16)
+#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
+#define P4_CCCR_ENABLE         (1<<12)
+#define P4_CCCR_OVF            (1<<31)
+/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
+   CRU_ESCR0 (with any non-null event selector) through a complemented
+   max threshold. [IA32-Vol3, Section 14.9.9] */
+
 static int setup_p4_watchdog(void)
 {
+       unsigned int perfctr_msr, evntsel_msr, cccr_msr;
+       unsigned int evntsel, cccr_val;
        unsigned int misc_enable, dummy;
+       unsigned int ht_num;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
-       rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
+       rdmsr(MSR_IA32_MISC_ENABLE, misc_enable, dummy);
        if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
                return 0;
 
-       nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
-       nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
 #ifdef CONFIG_SMP
-       if (smp_num_siblings == 2)
-               nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;
+       /* detect which hyperthread we are on */
+       if (smp_num_siblings == 2) {
+               unsigned int ebx, apicid;
+
+               ebx = cpuid_ebx(1);
+               apicid = (ebx >> 24) & 0xff;
+               ht_num = apicid & 1;
+       } else
 #endif
+               ht_num = 0;
 
-       if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
-               clear_msr_range(0x3F1, 2);
-       /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
-          docs doesn't fully define it, so leave it alone for now. */
-       if (boot_cpu_data.x86_model >= 0x3) {
-               /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
-               clear_msr_range(0x3A0, 26);
-               clear_msr_range(0x3BC, 3);
+       /* performance counters are shared resources
+        * assign each hyperthread its own set
+        * (re-use the ESCR0 register, seems safe
+        * and keeps the cccr_val the same)
+        */
+       if (!ht_num) {
+               /* logical cpu 0 */
+               perfctr_msr = MSR_P4_IQ_PERFCTR0;
+               evntsel_msr = MSR_P4_CRU_ESCR0;
+               cccr_msr = MSR_P4_IQ_CCCR0;
+               cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4);
        } else {
-               clear_msr_range(0x3A0, 31);
+               /* logical cpu 1 */
+               perfctr_msr = MSR_P4_IQ_PERFCTR1;
+               evntsel_msr = MSR_P4_CRU_ESCR0;
+               cccr_msr = MSR_P4_IQ_CCCR1;
+               cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4);
        }
-       clear_msr_range(0x3C0, 6);
-       clear_msr_range(0x3C8, 6);
-       clear_msr_range(0x3E0, 2);
-       clear_msr_range(MSR_P4_CCCR0, 18);
-       clear_msr_range(MSR_P4_PERFCTR0, 18);
-
-       wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
-       wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
-       write_watchdog_counter("P4_IQ_COUNTER0");
+
+       if (!reserve_perfctr_nmi(perfctr_msr))
+               goto fail;
+
+       if (!reserve_evntsel_nmi(evntsel_msr))
+               goto fail1;
+
+       evntsel = P4_ESCR_EVENT_SELECT(0x3F)
+               | P4_ESCR_OS
+               | P4_ESCR_USR;
+
+       cccr_val |= P4_CCCR_THRESHOLD(15)
+                | P4_CCCR_COMPLEMENT
+                | P4_CCCR_COMPARE
+                | P4_CCCR_REQUIRED;
+
+       wrmsr(evntsel_msr, evntsel, 0);
+       wrmsr(cccr_msr, cccr_val, 0);
+       write_watchdog_counter(perfctr_msr, "P4_IQ_COUNTER0");
        apic_write(APIC_LVTPC, APIC_DM_NMI);
-       wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
+       cccr_val |= P4_CCCR_ENABLE;
+       wrmsr(cccr_msr, cccr_val, 0);
+       wd->perfctr_msr = perfctr_msr;
+       wd->evntsel_msr = evntsel_msr;
+       wd->cccr_msr = cccr_msr;
+       wd->check_bit = 1ULL<<39;
        return 1;
+fail1:
+       release_perfctr_nmi(perfctr_msr);
+fail:
+       return 0;
 }
 
-static void disable_intel_arch_watchdog(void)
+static void stop_p4_watchdog(void)
 {
-       unsigned ebx;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
-       /*
-        * Check whether the Architectural PerfMon supports
-        * Unhalted Core Cycles Event or not.
-        * NOTE: Corresponding bit = 0 in ebp indicates event present.
-        */
-       ebx = cpuid_ebx(10);
-       if (!(ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
-               wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, 0, 0);
+       wrmsr(wd->cccr_msr, 0, 0);
+       wrmsr(wd->evntsel_msr, 0, 0);
+
+       release_evntsel_nmi(wd->evntsel_msr);
+       release_perfctr_nmi(wd->perfctr_msr);
 }
 
+#define ARCH_PERFMON_NMI_EVENT_SEL     ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
+#define ARCH_PERFMON_NMI_EVENT_UMASK   ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+
 static int setup_intel_arch_watchdog(void)
 {
+       unsigned int ebx;
+       union cpuid10_eax eax;
+       unsigned int unused;
+       unsigned int perfctr_msr, evntsel_msr;
        unsigned int evntsel;
-       unsigned ebx;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
        /*
         * Check whether the Architectural PerfMon supports
         * Unhalted Core Cycles Event or not.
-        * NOTE: Corresponding bit = 0 in ebp indicates event present.
+        * NOTE: Corresponding bit = 0 in ebx indicates event present.
         */
-       ebx = cpuid_ebx(10);
-       if ((ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
-               return 0;
+       cpuid(10, &(eax.full), &ebx, &unused, &unused);
+       if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
+           (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+               goto fail;
+
+       perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
+       evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL0;
 
-       nmi_perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
+       if (!reserve_perfctr_nmi(perfctr_msr))
+               goto fail;
 
-       clear_msr_range(MSR_ARCH_PERFMON_EVENTSEL0, 2);
-       clear_msr_range(MSR_ARCH_PERFMON_PERFCTR0, 2);
+       if (!reserve_evntsel_nmi(evntsel_msr))
+               goto fail1;
+
+       wrmsrl(perfctr_msr, 0UL);
 
        evntsel = ARCH_PERFMON_EVENTSEL_INT
                | ARCH_PERFMON_EVENTSEL_OS
@@ -493,51 +703,145 @@ static int setup_intel_arch_watchdog(void)
                | ARCH_PERFMON_NMI_EVENT_SEL
                | ARCH_PERFMON_NMI_EVENT_UMASK;
 
-       wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
-       write_watchdog_counter("INTEL_ARCH_PERFCTR0");
+       /* setup the timer */
+       wrmsr(evntsel_msr, evntsel, 0);
+       write_watchdog_counter(perfctr_msr, "INTEL_ARCH_PERFCTR0");
        apic_write(APIC_LVTPC, APIC_DM_NMI);
        evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
-       wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
+       wrmsr(evntsel_msr, evntsel, 0);
+
+       wd->perfctr_msr = perfctr_msr;
+       wd->evntsel_msr = evntsel_msr;
+       wd->cccr_msr = 0;  //unused
+       wd->check_bit = 1ULL << (eax.split.bit_width - 1);
        return 1;
+fail1:
+       release_perfctr_nmi(perfctr_msr);
+fail:
+       return 0;
 }
 
-void setup_apic_nmi_watchdog (void)
+static void stop_intel_arch_watchdog(void)
 {
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_AMD:
-               if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15)
-                       return;
-               setup_k7_watchdog();
-               break;
-       case X86_VENDOR_INTEL:
-               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
-                       if (!setup_intel_arch_watchdog())
+       unsigned int ebx;
+       union cpuid10_eax eax;
+       unsigned int unused;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       /*
+        * Check whether the Architectural PerfMon supports
+        * Unhalted Core Cycles Event or not.
+        * NOTE: Corresponding bit = 0 in ebx indicates event present.
+        */
+       cpuid(10, &(eax.full), &ebx, &unused, &unused);
+       if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
+           (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+               return;
+
+       wrmsr(wd->evntsel_msr, 0, 0);
+       release_evntsel_nmi(wd->evntsel_msr);
+       release_perfctr_nmi(wd->perfctr_msr);
+}
+
+void setup_apic_nmi_watchdog (void *unused)
+{
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       /* only support LOCAL and IO APICs for now */
+       if ((nmi_watchdog != NMI_LOCAL_APIC) &&
+           (nmi_watchdog != NMI_IO_APIC))
+               return;
+
+       if (wd->enabled == 1)
+               return;
+
+       /* cheap hack to support suspend/resume */
+       /* if cpu0 is not active neither should the other cpus */
+       if ((smp_processor_id() != 0) && (atomic_read(&nmi_active) <= 0))
+               return;
+
+       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)
                                return;
-                       break;
-               }
-               switch (boot_cpu_data.x86) {
-               case 6:
-                       if (boot_cpu_data.x86_model > 0xd)
+                       if (!setup_k7_watchdog())
                                return;
-
-                       setup_p6_watchdog();
                        break;
-               case 15:
-                       if (boot_cpu_data.x86_model > 0x4)
-                               return;
+               case X86_VENDOR_INTEL:
+                       if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+                               if (!setup_intel_arch_watchdog())
+                                       return;
+                               break;
+                       }
+                       switch (boot_cpu_data.x86) {
+                       case 6:
+                               if (boot_cpu_data.x86_model > 0xd)
+                                       return;
+
+                               if (!setup_p6_watchdog())
+                                       return;
+                               break;
+                       case 15:
+                               if (boot_cpu_data.x86_model > 0x4)
+                                       return;
 
-                       if (!setup_p4_watchdog())
+                               if (!setup_p4_watchdog())
+                                       return;
+                               break;
+                       default:
                                return;
+                       }
                        break;
                default:
                        return;
                }
-               break;
-       default:
+       }
+       wd->enabled = 1;
+       atomic_inc(&nmi_active);
+}
+
+void stop_apic_nmi_watchdog(void *unused)
+{
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       /* only support LOCAL and IO APICs for now */
+       if ((nmi_watchdog != NMI_LOCAL_APIC) &&
+           (nmi_watchdog != NMI_IO_APIC))
+               return;
+
+       if (wd->enabled == 0)
                return;
+
+       if (nmi_watchdog == NMI_LOCAL_APIC) {
+               switch (boot_cpu_data.x86_vendor) {
+               case X86_VENDOR_AMD:
+                       stop_k7_watchdog();
+                       break;
+               case X86_VENDOR_INTEL:
+                       if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+                               stop_intel_arch_watchdog();
+                               break;
+                       }
+                       switch (boot_cpu_data.x86) {
+                       case 6:
+                               if (boot_cpu_data.x86_model > 0xd)
+                                       break;
+                               stop_p6_watchdog();
+                               break;
+                       case 15:
+                               if (boot_cpu_data.x86_model > 0x4)
+                                       break;
+                               stop_p4_watchdog();
+                               break;
+                       }
+                       break;
+               default:
+                       return;
+               }
        }
-       lapic_nmi_owner = LAPIC_NMI_WATCHDOG;
-       nmi_active = 1;
+       wd->enabled = 0;
+       atomic_dec(&nmi_active);
 }
 
 /*
@@ -579,7 +883,7 @@ EXPORT_SYMBOL(touch_nmi_watchdog);
 
 extern void die_nmi(struct pt_regs *, const char *msg);
 
-void nmi_watchdog_tick (struct pt_regs * regs)
+__kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
 {
 
        /*
@@ -588,11 +892,23 @@ void nmi_watchdog_tick (struct pt_regs * regs)
         * smp_processor_id().
         */
        unsigned int sum;
+       int touched = 0;
        int cpu = smp_processor_id();
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+       u64 dummy;
+       int rc=0;
+
+       /* check for other users first */
+       if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
+                       == NOTIFY_STOP) {
+               rc = 1;
+               touched = 1;
+       }
 
        sum = per_cpu(irq_stat, cpu).apic_timer_irqs;
 
-       if (last_irq_sums[cpu] == sum) {
+       /* if the apic timer isn't firing, this cpu isn't doing much */
+       if (!touched && last_irq_sums[cpu] == sum) {
                /*
                 * Ayiee, looks like this CPU is stuck ...
                 * wait a few IRQs (5 seconds) before doing the oops ...
@@ -607,27 +923,59 @@ void nmi_watchdog_tick (struct pt_regs * regs)
                last_irq_sums[cpu] = sum;
                alert_counter[cpu] = 0;
        }
-       if (nmi_perfctr_msr) {
-               if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
-                       /*
-                        * P4 quirks:
-                        * - An overflown perfctr will assert its interrupt
-                        *   until the OVF flag in its CCCR is cleared.
-                        * - LVTPC is masked on interrupt and must be
-                        *   unmasked by the LVTPC handler.
+       /* see if the nmi watchdog went off */
+       if (wd->enabled) {
+               if (nmi_watchdog == NMI_LOCAL_APIC) {
+                       rdmsrl(wd->perfctr_msr, dummy);
+                       if (dummy & wd->check_bit){
+                               /* this wasn't a watchdog timer interrupt */
+                               goto done;
+                       }
+
+                       /* only Intel P4 uses the cccr msr */
+                       if (wd->cccr_msr != 0) {
+                               /*
+                                * P4 quirks:
+                                * - An overflown perfctr will assert its interrupt
+                                *   until the OVF flag in its CCCR is cleared.
+                                * - LVTPC is masked on interrupt and must be
+                                *   unmasked by the LVTPC handler.
+                                */
+                               rdmsrl(wd->cccr_msr, dummy);
+                               dummy &= ~P4_CCCR_OVF;
+                               wrmsrl(wd->cccr_msr, dummy);
+                               apic_write(APIC_LVTPC, APIC_DM_NMI);
+                       }
+                       else if (wd->perfctr_msr == MSR_P6_PERFCTR0 ||
+                                wd->perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
+                               /* P6 based Pentium M need to re-unmask
+                                * the apic vector but it doesn't hurt
+                                * other P6 variant.
+                                * ArchPerfom/Core Duo also needs this */
+                               apic_write(APIC_LVTPC, APIC_DM_NMI);
+                       }
+                       /* 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.
+                        * just assume it was a watchdog timer interrupt
+                        * This matches the old behaviour.
                         */
-                       wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
-                       apic_write(APIC_LVTPC, APIC_DM_NMI);
+                       rc = 1;
                }
-               else if (nmi_perfctr_msr == MSR_P6_PERFCTR0 ||
-                        nmi_perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
-                       /* Only P6 based Pentium M need to re-unmask
-                        * the apic vector but it doesn't hurt
-                        * other P6 variant */
-                       apic_write(APIC_LVTPC, APIC_DM_NMI);
-               }
-               write_watchdog_counter(NULL);
        }
+done:
+       return rc;
+}
+
+int do_nmi_callback(struct pt_regs * regs, int cpu)
+{
+#ifdef CONFIG_SYSCTL
+       if (unknown_nmi_panic)
+               return unknown_nmi_panic_callback(regs, cpu);
+#endif
+       return 0;
 }
 
 #ifdef CONFIG_SYSCTL
@@ -637,36 +985,46 @@ static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu)
        unsigned char reason = get_nmi_reason();
        char buf[64];
 
-       if (!(reason & 0xc0)) {
-               sprintf(buf, "NMI received for unknown reason %02x\n", reason);
-               die_nmi(regs, buf);
-       }
+       sprintf(buf, "NMI received for unknown reason %02x\n", reason);
+       die_nmi(regs, buf);
        return 0;
 }
 
 /*
- * proc handler for /proc/sys/kernel/unknown_nmi_panic
+ * proc handler for /proc/sys/kernel/nmi
  */
-int proc_unknown_nmi_panic(ctl_table *table, int write, struct file *file,
+int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file,
                        void __user *buffer, size_t *length, loff_t *ppos)
 {
        int old_state;
 
-       old_state = unknown_nmi_panic;
+       nmi_watchdog_enabled = (atomic_read(&nmi_active) > 0) ? 1 : 0;
+       old_state = nmi_watchdog_enabled;
        proc_dointvec(table, write, file, buffer, length, ppos);
-       if (!!old_state == !!unknown_nmi_panic)
+       if (!!old_state == !!nmi_watchdog_enabled)
                return 0;
 
-       if (unknown_nmi_panic) {
-               if (reserve_lapic_nmi() < 0) {
-                       unknown_nmi_panic = 0;
-                       return -EBUSY;
-               } else {
-                       set_nmi_callback(unknown_nmi_panic_callback);
-               }
+       if (atomic_read(&nmi_active) < 0) {
+               printk( KERN_WARNING "NMI watchdog is permanently disabled\n");
+               return -EIO;
+       }
+
+       if (nmi_watchdog == NMI_DEFAULT) {
+               if (nmi_known_cpu() > 0)
+                       nmi_watchdog = NMI_LOCAL_APIC;
+               else
+                       nmi_watchdog = NMI_IO_APIC;
+       }
+
+       if (nmi_watchdog == NMI_LOCAL_APIC) {
+               if (nmi_watchdog_enabled)
+                       enable_lapic_nmi_watchdog();
+               else
+                       disable_lapic_nmi_watchdog();
        } else {
-               release_lapic_nmi();
-               unset_nmi_callback();
+               printk( KERN_WARNING
+                       "NMI watchdog doesn't know what hardware to touch\n");
+               return -EIO;
        }
        return 0;
 }
@@ -675,7 +1033,11 @@ int proc_unknown_nmi_panic(ctl_table *table, int write, struct file *file,
 
 EXPORT_SYMBOL(nmi_active);
 EXPORT_SYMBOL(nmi_watchdog);
-EXPORT_SYMBOL(reserve_lapic_nmi);
-EXPORT_SYMBOL(release_lapic_nmi);
+EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi);
+EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi_bit);
+EXPORT_SYMBOL(reserve_perfctr_nmi);
+EXPORT_SYMBOL(release_perfctr_nmi);
+EXPORT_SYMBOL(reserve_evntsel_nmi);
+EXPORT_SYMBOL(release_evntsel_nmi);
 EXPORT_SYMBOL(disable_timer_nmi_watchdog);
 EXPORT_SYMBOL(enable_timer_nmi_watchdog);
index 8657c739656a37bbcef81cb36accb486902cf5d1..8c190ca7ae4494b980b01c8a4c88eee291a3fd45 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/kallsyms.h>
 #include <linux/ptrace.h>
 #include <linux/random.h>
+#include <linux/personality.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -320,15 +321,6 @@ void show_regs(struct pt_regs * regs)
  * the "args".
  */
 extern void kernel_thread_helper(void);
-__asm__(".section .text\n"
-       ".align 4\n"
-       "kernel_thread_helper:\n\t"
-       "movl %edx,%eax\n\t"
-       "pushl %edx\n\t"
-       "call *%ebx\n\t"
-       "pushl %eax\n\t"
-       "call do_exit\n"
-       ".previous");
 
 /*
  * Create a kernel thread
@@ -346,7 +338,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
        regs.xes = __USER_DS;
        regs.orig_eax = -1;
        regs.eip = (unsigned long) kernel_thread_helper;
-       regs.xcs = __KERNEL_CS;
+       regs.xcs = __KERNEL_CS | get_kernel_rpl();
        regs.eflags = X86_EFLAGS_IF | X86_EFLAGS_SF | X86_EFLAGS_PF | 0x2;
 
        /* Ok, create the new process.. */
@@ -905,7 +897,7 @@ asmlinkage int sys_get_thread_area(struct user_desc __user *u_info)
 
 unsigned long arch_align_stack(unsigned long sp)
 {
-       if (randomize_va_space)
+       if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
                sp -= get_random_int() % 8192;
        return sp & ~0xf;
 }
index d3db03f4085d75ef607acda75e020cf0c0f10ffe..775f50e9395bb048a2e193ef60483af172c7c045 100644 (file)
@@ -185,17 +185,17 @@ static unsigned long convert_eip_to_linear(struct task_struct *child, struct pt_
        return addr;
 }
 
-static inline int is_at_popf(struct task_struct *child, struct pt_regs *regs)
+static inline int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
 {
        int i, copied;
-       unsigned char opcode[16];
+       unsigned char opcode[15];
        unsigned long addr = convert_eip_to_linear(child, regs);
 
        copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
        for (i = 0; i < copied; i++) {
                switch (opcode[i]) {
-               /* popf */
-               case 0x9d:
+               /* popf and iret */
+               case 0x9d: case 0xcf:
                        return 1;
                /* opcode and address size prefixes */
                case 0x66: case 0x67:
@@ -247,7 +247,7 @@ static void set_singlestep(struct task_struct *child)
         * don't mark it as being "us" that set it, so that we
         * won't clear it by hand later.
         */
-       if (is_at_popf(child, regs))
+       if (is_setting_trap_flag(child, regs))
                return;
        
        child->ptrace |= PT_DTRACE;
index d312616effa132570be2178b642ecace7bb9f2cb..f151d6fae462a3fb204f4847018e846dfdcccbca 100644 (file)
  */
 
 #include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/kexec.h>
+
+/*
+ * Must be relocatable PIC code callable as a C function
+ */
+
+#define PTR(x) (x << 2)
+#define PAGE_ALIGNED (1 << PAGE_SHIFT)
+#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
+#define PAE_PGD_ATTR 0x01 /* _PAGE_PRESENT */
+
+       .text
+       .align PAGE_ALIGNED
+       .globl relocate_kernel
+relocate_kernel:
+       movl    8(%esp), %ebp /* list of pages */
+
+#ifdef CONFIG_X86_PAE
+       /* map the control page at its virtual address */
+
+       movl    PTR(VA_PGD)(%ebp), %edi
+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
+       andl    $0xc0000000, %eax
+       shrl    $27, %eax
+       addl    %edi, %eax
+
+       movl    PTR(PA_PMD_0)(%ebp), %edx
+       orl     $PAE_PGD_ATTR, %edx
+       movl    %edx, (%eax)
+
+       movl    PTR(VA_PMD_0)(%ebp), %edi
+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
+       andl    $0x3fe00000, %eax
+       shrl    $18, %eax
+       addl    %edi, %eax
+
+       movl    PTR(PA_PTE_0)(%ebp), %edx
+       orl     $PAGE_ATTR, %edx
+       movl    %edx, (%eax)
+
+       movl    PTR(VA_PTE_0)(%ebp), %edi
+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
+       andl    $0x001ff000, %eax
+       shrl    $9, %eax
+       addl    %edi, %eax
+
+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
+       orl     $PAGE_ATTR, %edx
+       movl    %edx, (%eax)
+
+       /* identity map the control page at its physical address */
+
+       movl    PTR(VA_PGD)(%ebp), %edi
+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
+       andl    $0xc0000000, %eax
+       shrl    $27, %eax
+       addl    %edi, %eax
+
+       movl    PTR(PA_PMD_1)(%ebp), %edx
+       orl     $PAE_PGD_ATTR, %edx
+       movl    %edx, (%eax)
+
+       movl    PTR(VA_PMD_1)(%ebp), %edi
+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
+       andl    $0x3fe00000, %eax
+       shrl    $18, %eax
+       addl    %edi, %eax
+
+       movl    PTR(PA_PTE_1)(%ebp), %edx
+       orl     $PAGE_ATTR, %edx
+       movl    %edx, (%eax)
+
+       movl    PTR(VA_PTE_1)(%ebp), %edi
+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
+       andl    $0x001ff000, %eax
+       shrl    $9, %eax
+       addl    %edi, %eax
+
+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
+       orl     $PAGE_ATTR, %edx
+       movl    %edx, (%eax)
+#else
+       /* map the control page at its virtual address */
+
+       movl    PTR(VA_PGD)(%ebp), %edi
+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
+       andl    $0xffc00000, %eax
+       shrl    $20, %eax
+       addl    %edi, %eax
+
+       movl    PTR(PA_PTE_0)(%ebp), %edx
+       orl     $PAGE_ATTR, %edx
+       movl    %edx, (%eax)
+
+       movl    PTR(VA_PTE_0)(%ebp), %edi
+       movl    PTR(VA_CONTROL_PAGE)(%ebp), %eax
+       andl    $0x003ff000, %eax
+       shrl    $10, %eax
+       addl    %edi, %eax
+
+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
+       orl     $PAGE_ATTR, %edx
+       movl    %edx, (%eax)
+
+       /* identity map the control page at its physical address */
+
+       movl    PTR(VA_PGD)(%ebp), %edi
+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
+       andl    $0xffc00000, %eax
+       shrl    $20, %eax
+       addl    %edi, %eax
+
+       movl    PTR(PA_PTE_1)(%ebp), %edx
+       orl     $PAGE_ATTR, %edx
+       movl    %edx, (%eax)
+
+       movl    PTR(VA_PTE_1)(%ebp), %edi
+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %eax
+       andl    $0x003ff000, %eax
+       shrl    $10, %eax
+       addl    %edi, %eax
+
+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %edx
+       orl     $PAGE_ATTR, %edx
+       movl    %edx, (%eax)
+#endif
 
-       /*
-        * Must be relocatable PIC code callable as a C function, that once
-        * it starts can not use the previous processes stack.
-        */
-       .globl relocate_new_kernel
 relocate_new_kernel:
        /* read the arguments and say goodbye to the stack */
        movl  4(%esp), %ebx /* page_list */
-       movl  8(%esp), %ebp /* reboot_code_buffer */
+       movl  8(%esp), %ebp /* list of pages */
        movl  12(%esp), %edx /* start address */
        movl  16(%esp), %ecx /* cpu_has_pae */
 
@@ -24,11 +146,26 @@ relocate_new_kernel:
        pushl $0
        popfl
 
-       /* set a new stack at the bottom of our page... */
-       lea   4096(%ebp), %esp
+       /* get physical address of control page now */
+       /* this is impossible after page table switch */
+       movl    PTR(PA_CONTROL_PAGE)(%ebp), %edi
 
-       /* store the parameters back on the stack */
-       pushl   %edx /* store the start address */
+       /* switch to new set of page tables */
+       movl    PTR(PA_PGD)(%ebp), %eax
+       movl    %eax, %cr3
+
+       /* setup a new stack at the end of the physical control page */
+       lea     4096(%edi), %esp
+
+       /* jump to identity mapped page */
+       movl    %edi, %eax
+       addl    $(identity_mapped - relocate_kernel), %eax
+       pushl   %eax
+       ret
+
+identity_mapped:
+       /* store the start address on the stack */
+       pushl   %edx
 
        /* Set cr0 to a known state:
         * 31 0 == Paging disabled
@@ -113,8 +250,3 @@ relocate_new_kernel:
        xorl    %edi, %edi
        xorl    %ebp, %ebp
        ret
-relocate_new_kernel_end:
-
-       .globl relocate_new_kernel_size
-relocate_new_kernel_size:
-       .long relocate_new_kernel_end - relocate_new_kernel
diff --git a/arch/i386/kernel/semaphore.c b/arch/i386/kernel/semaphore.c
deleted file mode 100644 (file)
index 98352c3..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * i386 semaphore implementation.
- *
- * (C) Copyright 1999 Linus Torvalds
- *
- * Portions Copyright 1999 Red Hat, 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.
- *
- * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
- */
-#include <asm/semaphore.h>
-
-/*
- * The semaphore operations have a special calling sequence that
- * allow us to do a simpler in-line version of them. These routines
- * need to convert that sequence back into the C sequence when
- * there is contention on the semaphore.
- *
- * %eax contains the semaphore pointer on entry. Save the C-clobbered
- * registers (%eax, %edx and %ecx) except %eax whish is either a return
- * value or just clobbered..
- */
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __down_failed\n"
-"__down_failed:\n\t"
-#if defined(CONFIG_FRAME_POINTER)
-       "pushl %ebp\n\t"
-       "movl  %esp,%ebp\n\t"
-#endif
-       "pushl %edx\n\t"
-       "pushl %ecx\n\t"
-       "call __down\n\t"
-       "popl %ecx\n\t"
-       "popl %edx\n\t"
-#if defined(CONFIG_FRAME_POINTER)
-       "movl %ebp,%esp\n\t"
-       "popl %ebp\n\t"
-#endif
-       "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __down_failed_interruptible\n"
-"__down_failed_interruptible:\n\t"
-#if defined(CONFIG_FRAME_POINTER)
-       "pushl %ebp\n\t"
-       "movl  %esp,%ebp\n\t"
-#endif
-       "pushl %edx\n\t"
-       "pushl %ecx\n\t"
-       "call __down_interruptible\n\t"
-       "popl %ecx\n\t"
-       "popl %edx\n\t"
-#if defined(CONFIG_FRAME_POINTER)
-       "movl %ebp,%esp\n\t"
-       "popl %ebp\n\t"
-#endif
-       "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __down_failed_trylock\n"
-"__down_failed_trylock:\n\t"
-#if defined(CONFIG_FRAME_POINTER)
-       "pushl %ebp\n\t"
-       "movl  %esp,%ebp\n\t"
-#endif
-       "pushl %edx\n\t"
-       "pushl %ecx\n\t"
-       "call __down_trylock\n\t"
-       "popl %ecx\n\t"
-       "popl %edx\n\t"
-#if defined(CONFIG_FRAME_POINTER)
-       "movl %ebp,%esp\n\t"
-       "popl %ebp\n\t"
-#endif
-       "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align 4\n"
-".globl __up_wakeup\n"
-"__up_wakeup:\n\t"
-       "pushl %edx\n\t"
-       "pushl %ecx\n\t"
-       "call __up\n\t"
-       "popl %ecx\n\t"
-       "popl %edx\n\t"
-       "ret"
-);
-
-/*
- * rw spinlock fallbacks
- */
-#if defined(CONFIG_SMP)
-asm(
-".section .sched.text\n"
-".align        4\n"
-".globl        __write_lock_failed\n"
-"__write_lock_failed:\n\t"
-       LOCK_PREFIX "addl       $" RW_LOCK_BIAS_STR ",(%eax)\n"
-"1:    rep; nop\n\t"
-       "cmpl   $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
-       "jne    1b\n\t"
-       LOCK_PREFIX "subl       $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
-       "jnz    __write_lock_failed\n\t"
-       "ret"
-);
-
-asm(
-".section .sched.text\n"
-".align        4\n"
-".globl        __read_lock_failed\n"
-"__read_lock_failed:\n\t"
-       LOCK_PREFIX "incl       (%eax)\n"
-"1:    rep; nop\n\t"
-       "cmpl   $1,(%eax)\n\t"
-       "js     1b\n\t"
-       LOCK_PREFIX "decl       (%eax)\n\t"
-       "js     __read_lock_failed\n\t"
-       "ret"
-);
-#endif
index 16d99444cf66653c446e59534cc9f8e9f704643a..814cdebf73773ed73b2a7228179067f5f7c972dc 100644 (file)
@@ -90,18 +90,6 @@ EXPORT_SYMBOL(boot_cpu_data);
 
 unsigned long mmu_cr4_features;
 
-#ifdef CONFIG_ACPI
-       int acpi_disabled = 0;
-#else
-       int acpi_disabled = 1;
-#endif
-EXPORT_SYMBOL(acpi_disabled);
-
-#ifdef CONFIG_ACPI
-int __initdata acpi_force = 0;
-extern acpi_interrupt_flags    acpi_sci_flags;
-#endif
-
 /* for MCA, but anyone else can use it if they want */
 unsigned int machine_id;
 #ifdef CONFIG_MCA
@@ -149,7 +137,6 @@ EXPORT_SYMBOL(ist_info);
 struct e820map e820;
 
 extern void early_cpu_init(void);
-extern void generic_apic_probe(char *);
 extern int root_mountflags;
 
 unsigned long saved_videomode;
@@ -701,238 +688,132 @@ static inline void copy_edd(void)
 }
 #endif
 
-static void __init parse_cmdline_early (char ** cmdline_p)
-{
-       char c = ' ', *to = command_line, *from = saved_command_line;
-       int len = 0;
-       int userdef = 0;
+static int __initdata user_defined_memmap = 0;
 
-       /* Save unparsed command line copy for /proc/cmdline */
-       saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+/*
+ * "mem=nopentium" disables the 4MB page tables.
+ * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
+ * to <mem>, overriding the bios size.
+ * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
+ * <start> to <start>+<mem>, overriding the bios size.
+ *
+ * HPA tells me bootloaders need to parse mem=, so no new
+ * option should be mem=  [also see Documentation/i386/boot.txt]
+ */
+static int __init parse_mem(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
 
-       for (;;) {
-               if (c != ' ')
-                       goto next_char;
-               /*
-                * "mem=nopentium" disables the 4MB page tables.
-                * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
-                * to <mem>, overriding the bios size.
-                * "memmap=XXX[KkmM]@XXX[KkmM]" defines a memory region from
-                * <start> to <start>+<mem>, overriding the bios size.
-                *
-                * HPA tells me bootloaders need to parse mem=, so no new
-                * option should be mem=  [also see Documentation/i386/boot.txt]
+       if (strcmp(arg, "nopentium") == 0) {
+               clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+               disable_pse = 1;
+       } else {
+               /* If the user specifies memory size, we
+                * limit the BIOS-provided memory map to
+                * that size. exactmap can be used to specify
+                * the exact map. mem=number can be used to
+                * trim the existing memory map.
                 */
-               if (!memcmp(from, "mem=", 4)) {
-                       if (to != command_line)
-                               to--;
-                       if (!memcmp(from+4, "nopentium", 9)) {
-                               from += 9+4;
-                               clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
-                               disable_pse = 1;
-                       } else {
-                               /* If the user specifies memory size, we
-                                * limit the BIOS-provided memory map to
-                                * that size. exactmap can be used to specify
-                                * the exact map. mem=number can be used to
-                                * trim the existing memory map.
-                                */
-                               unsigned long long mem_size;
+               unsigned long long mem_size;
  
-                               mem_size = memparse(from+4, &from);
-                               limit_regions(mem_size);
-                               userdef=1;
-                       }
-               }
-
-               else if (!memcmp(from, "memmap=", 7)) {
-                       if (to != command_line)
-                               to--;
-                       if (!memcmp(from+7, "exactmap", 8)) {
-#ifdef CONFIG_CRASH_DUMP
-                               /* If we are doing a crash dump, we
-                                * still need to know the real mem
-                                * size before original memory map is
-                                * reset.
-                                */
-                               find_max_pfn();
-                               saved_max_pfn = max_pfn;
-#endif
-                               from += 8+7;
-                               e820.nr_map = 0;
-                               userdef = 1;
-                       } else {
-                               /* If the user specifies memory size, we
-                                * limit the BIOS-provided memory map to
-                                * that size. exactmap can be used to specify
-                                * the exact map. mem=number can be used to
-                                * trim the existing memory map.
-                                */
-                               unsigned long long start_at, mem_size;
-                               mem_size = memparse(from+7, &from);
-                               if (*from == '@') {
-                                       start_at = memparse(from+1, &from);
-                                       add_memory_region(start_at, mem_size, E820_RAM);
-                               } else if (*from == '#') {
-                                       start_at = memparse(from+1, &from);
-                                       add_memory_region(start_at, mem_size, E820_ACPI);
-                               } else if (*from == '$') {
-                                       start_at = memparse(from+1, &from);
-                                       add_memory_region(start_at, mem_size, E820_RESERVED);
-                               } else {
-                                       limit_regions(mem_size);
-                                       userdef=1;
-                               }
-                       }
-               }
-
-               else if (!memcmp(from, "noexec=", 7))
-                       noexec_setup(from + 7);
+               mem_size = memparse(arg, &arg);
+               limit_regions(mem_size);
+               user_defined_memmap = 1;
+       }
+       return 0;
+}
+early_param("mem", parse_mem);
 
+static int __init parse_memmap(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
 
-#ifdef  CONFIG_X86_SMP
-               /*
-                * If the BIOS enumerates physical processors before logical,
-                * maxcpus=N at enumeration-time can be used to disable HT.
+       if (strcmp(arg, "exactmap") == 0) {
+#ifdef CONFIG_CRASH_DUMP
+               /* If we are doing a crash dump, we
+                * still need to know the real mem
+                * size before original memory map is
+                * reset.
                 */
-               else if (!memcmp(from, "maxcpus=", 8)) {
-                       extern unsigned int maxcpus;
-
-                       maxcpus = simple_strtoul(from + 8, NULL, 0);
-               }
+               find_max_pfn();
+               saved_max_pfn = max_pfn;
 #endif
-
-#ifdef CONFIG_ACPI
-               /* "acpi=off" disables both ACPI table parsing and interpreter */
-               else if (!memcmp(from, "acpi=off", 8)) {
-                       disable_acpi();
-               }
-
-               /* acpi=force to over-ride black-list */
-               else if (!memcmp(from, "acpi=force", 10)) {
-                       acpi_force = 1;
-                       acpi_ht = 1;
-                       acpi_disabled = 0;
-               }
-
-               /* acpi=strict disables out-of-spec workarounds */
-               else if (!memcmp(from, "acpi=strict", 11)) {
-                       acpi_strict = 1;
-               }
-
-               /* Limit ACPI just to boot-time to enable HT */
-               else if (!memcmp(from, "acpi=ht", 7)) {
-                       if (!acpi_force)
-                               disable_acpi();
-                       acpi_ht = 1;
-               }
-               
-               /* "pci=noacpi" disable ACPI IRQ routing and PCI scan */
-               else if (!memcmp(from, "pci=noacpi", 10)) {
-                       acpi_disable_pci();
-               }
-               /* "acpi=noirq" disables ACPI interrupt routing */
-               else if (!memcmp(from, "acpi=noirq", 10)) {
-                       acpi_noirq_set();
+               e820.nr_map = 0;
+               user_defined_memmap = 1;
+       } else {
+               /* If the user specifies memory size, we
+                * limit the BIOS-provided memory map to
+                * that size. exactmap can be used to specify
+                * the exact map. mem=number can be used to
+                * trim the existing memory map.
+                */
+               unsigned long long start_at, mem_size;
+
+               mem_size = memparse(arg, &arg);
+               if (*arg == '@') {
+                       start_at = memparse(arg+1, &arg);
+                       add_memory_region(start_at, mem_size, E820_RAM);
+               } else if (*arg == '#') {
+                       start_at = memparse(arg+1, &arg);
+                       add_memory_region(start_at, mem_size, E820_ACPI);
+               } else if (*arg == '$') {
+                       start_at = memparse(arg+1, &arg);
+                       add_memory_region(start_at, mem_size, E820_RESERVED);
+               } else {
+                       limit_regions(mem_size);
+                       user_defined_memmap = 1;
                }
+       }
+       return 0;
+}
+early_param("memmap", parse_memmap);
 
-               else if (!memcmp(from, "acpi_sci=edge", 13))
-                       acpi_sci_flags.trigger =  1;
-
-               else if (!memcmp(from, "acpi_sci=level", 14))
-                       acpi_sci_flags.trigger = 3;
-
-               else if (!memcmp(from, "acpi_sci=high", 13))
-                       acpi_sci_flags.polarity = 1;
-
-               else if (!memcmp(from, "acpi_sci=low", 12))
-                       acpi_sci_flags.polarity = 3;
-
-#ifdef CONFIG_X86_IO_APIC
-               else if (!memcmp(from, "acpi_skip_timer_override", 24))
-                       acpi_skip_timer_override = 1;
-
-               if (!memcmp(from, "disable_timer_pin_1", 19))
-                       disable_timer_pin_1 = 1;
-               if (!memcmp(from, "enable_timer_pin_1", 18))
-                       disable_timer_pin_1 = -1;
+#ifdef CONFIG_PROC_VMCORE
+/* elfcorehdr= specifies the location of elf core header
+ * stored by the crashed kernel.
+ */
+static int __init parse_elfcorehdr(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
 
-               /* disable IO-APIC */
-               else if (!memcmp(from, "noapic", 6))
-                       disable_ioapic_setup();
-#endif /* CONFIG_X86_IO_APIC */
-#endif /* CONFIG_ACPI */
+       elfcorehdr_addr = memparse(arg, &arg);
+       return 0;
+}
+early_param("elfcorehdr", parse_elfcorehdr);
+#endif /* CONFIG_PROC_VMCORE */
 
-#ifdef CONFIG_X86_LOCAL_APIC
-               /* enable local APIC */
-               else if (!memcmp(from, "lapic", 5))
-                       lapic_enable();
+/*
+ * highmem=size forces highmem to be exactly 'size' bytes.
+ * This works even on boxes that have no highmem otherwise.
+ * This also works to reduce highmem size on bigger boxes.
+ */
+static int __init parse_highmem(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
 
-               /* disable local APIC */
-               else if (!memcmp(from, "nolapic", 6))
-                       lapic_disable();
-#endif /* CONFIG_X86_LOCAL_APIC */
+       highmem_pages = memparse(arg, &arg) >> PAGE_SHIFT;
+       return 0;
+}
+early_param("highmem", parse_highmem);
 
-#ifdef CONFIG_KEXEC
-               /* crashkernel=size@addr specifies the location to reserve for
-                * a crash kernel.  By reserving this memory we guarantee
-                * that linux never set's it up as a DMA target.
-                * Useful for holding code to do something appropriate
-                * after a kernel panic.
-                */
-               else if (!memcmp(from, "crashkernel=", 12)) {
-                       unsigned long size, base;
-                       size = memparse(from+12, &from);
-                       if (*from == '@') {
-                               base = memparse(from+1, &from);
-                               /* FIXME: Do I want a sanity check
-                                * to validate the memory range?
-                                */
-                               crashk_res.start = base;
-                               crashk_res.end   = base + size - 1;
-                       }
-               }
-#endif
-#ifdef CONFIG_PROC_VMCORE
-               /* elfcorehdr= specifies the location of elf core header
-                * stored by the crashed kernel.
-                */
-               else if (!memcmp(from, "elfcorehdr=", 11))
-                       elfcorehdr_addr = memparse(from+11, &from);
-#endif
+/*
+ * vmalloc=size forces the vmalloc area to be exactly 'size'
+ * bytes. This can be used to increase (or decrease) the
+ * vmalloc area - the default is 128m.
+ */
+static int __init parse_vmalloc(char *arg)
+{
+       if (!arg)
+               return -EINVAL;
 
-               /*
-                * highmem=size forces highmem to be exactly 'size' bytes.
-                * This works even on boxes that have no highmem otherwise.
-                * This also works to reduce highmem size on bigger boxes.
-                */
-               else if (!memcmp(from, "highmem=", 8))
-                       highmem_pages = memparse(from+8, &from) >> PAGE_SHIFT;
-       
-               /*
-                * vmalloc=size forces the vmalloc area to be exactly 'size'
-                * bytes. This can be used to increase (or decrease) the
-                * vmalloc area - the default is 128m.
-                */
-               else if (!memcmp(from, "vmalloc=", 8))
-                       __VMALLOC_RESERVE = memparse(from+8, &from);
-
-       next_char:
-               c = *(from++);
-               if (!c)
-                       break;
-               if (COMMAND_LINE_SIZE <= ++len)
-                       break;
-               *(to++) = c;
-       }
-       *to = '\0';
-       *cmdline_p = command_line;
-       if (userdef) {
-               printk(KERN_INFO "user-defined physical RAM map:\n");
-               print_memory_map("user");
-       }
+       __VMALLOC_RESERVE = memparse(arg, &arg);
+       return 0;
 }
+early_param("vmalloc", parse_vmalloc);
 
 /*
  * reservetop=size reserves a hole at the top of the kernel address space which
@@ -1189,6 +1070,14 @@ static unsigned long __init setup_memory(void)
        }
        printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
                pages_to_mb(highend_pfn - highstart_pfn));
+       num_physpages = highend_pfn;
+       high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
+#else
+       num_physpages = max_low_pfn;
+       high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
+#endif
+#ifdef CONFIG_FLATMEM
+       max_mapnr = num_physpages;
 #endif
        printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
                        pages_to_mb(max_low_pfn));
@@ -1200,22 +1089,20 @@ static unsigned long __init setup_memory(void)
 
 void __init zone_sizes_init(void)
 {
-       unsigned long zones_size[MAX_NR_ZONES] = { 0, };
-       unsigned int max_dma, low;
-
-       max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-       low = max_low_pfn;
-
-       if (low < max_dma)
-               zones_size[ZONE_DMA] = low;
-       else {
-               zones_size[ZONE_DMA] = max_dma;
-               zones_size[ZONE_NORMAL] = low - max_dma;
 #ifdef CONFIG_HIGHMEM
-               zones_size[ZONE_HIGHMEM] = highend_pfn - low;
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+                       virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
+                       max_low_pfn,
+                       highend_pfn};
+       add_active_range(0, 0, highend_pfn);
+#else
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+                       virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
+                       max_low_pfn};
+       add_active_range(0, 0, max_low_pfn);
 #endif
-       }
-       free_area_init(zones_size);
+
+       free_area_init_nodes(max_zone_pfns);
 }
 #else
 extern unsigned long __init setup_memory(void);
@@ -1518,17 +1405,15 @@ void __init setup_arch(char **cmdline_p)
        data_resource.start = virt_to_phys(_etext);
        data_resource.end = virt_to_phys(_edata)-1;
 
-       parse_cmdline_early(cmdline_p);
+       parse_early_param();
 
-#ifdef CONFIG_EARLY_PRINTK
-       {
-               char *s = strstr(*cmdline_p, "earlyprintk=");
-               if (s) {
-                       setup_early_printk(strchr(s, '=') + 1);
-                       printk("early console enabled\n");
-               }
+       if (user_defined_memmap) {
+               printk(KERN_INFO "user-defined physical RAM map:\n");
+               print_memory_map("user");
        }
-#endif
+
+       strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+       *cmdline_p = command_line;
 
        max_low_pfn = setup_memory();
 
@@ -1557,7 +1442,7 @@ void __init setup_arch(char **cmdline_p)
        dmi_scan_machine();
 
 #ifdef CONFIG_X86_GENERICARCH
-       generic_apic_probe(*cmdline_p);
+       generic_apic_probe();
 #endif 
        if (efi_enabled)
                efi_map_memmap();
@@ -1569,9 +1454,11 @@ void __init setup_arch(char **cmdline_p)
        acpi_boot_table_init();
 #endif
 
+#ifdef CONFIG_PCI
 #ifdef CONFIG_X86_IO_APIC
        check_acpi_pci();       /* Checks more than just ACPI actually */
 #endif
+#endif
 
 #ifdef CONFIG_ACPI
        acpi_boot_init();
index efe07990e7fca6e6508b8e5ceb54caa55bad47c8..020d873b7d2130584e84906186703c8cd6079498 100644 (file)
@@ -177,6 +177,9 @@ static void __devinit smp_store_cpu_info(int id)
         */
        if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
 
+               if (num_possible_cpus() == 1)
+                       goto valid_k7;
+
                /* Athlon 660/661 is valid. */  
                if ((c->x86_model==6) && ((c->x86_mask==0) || (c->x86_mask==1)))
                        goto valid_k7;
@@ -1376,7 +1379,8 @@ int __cpu_disable(void)
         */
        if (cpu == 0)
                return -EBUSY;
-
+       if (nmi_watchdog == NMI_LOCAL_APIC)
+               stop_apic_nmi_watchdog(NULL);
        clear_local_APIC();
        /* Allow any queued timer interrupts to get serviced */
        local_irq_enable();
@@ -1490,3 +1494,16 @@ void __init smp_intr_init(void)
        /* IPI for generic function call */
        set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
 }
+
+/*
+ * If the BIOS enumerates physical processors before logical,
+ * maxcpus=N at enumeration-time can be used to disable HT.
+ */
+static int __init parse_maxcpus(char *arg)
+{
+       extern unsigned int maxcpus;
+
+       maxcpus = simple_strtoul(arg, NULL, 0);
+       return 0;
+}
+early_param("maxcpus", parse_maxcpus);
index 83db411b3aa7a4be27fc987a14666629616ea200..32413122c4c2650f1114db0f10bb1d8e12c116b8 100644 (file)
@@ -54,8 +54,6 @@ struct node_memory_chunk_s {
 static struct node_memory_chunk_s node_memory_chunk[MAXCHUNKS];
 
 static int num_memory_chunks;          /* total number of memory chunks */
-static int zholes_size_init;
-static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
 
 extern void * boot_ioremap(unsigned long, unsigned long);
 
@@ -135,47 +133,6 @@ static void __init parse_memory_affinity_structure (char *sratp)
                 "enabled and removable" : "enabled" ) );
 }
 
-/* Take a chunk of pages from page frame cstart to cend and count the number
- * of pages in each zone, returned via zones[].
- */
-static __init void chunk_to_zones(unsigned long cstart, unsigned long cend, 
-               unsigned long *zones)
-{
-       unsigned long max_dma;
-       extern unsigned long max_low_pfn;
-
-       int z;
-       unsigned long rend;
-
-       /* FIXME: MAX_DMA_ADDRESS and max_low_pfn are trying to provide
-        * similarly scoped information and should be handled in a consistant
-        * manner.
-        */
-       max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-
-       /* Split the hole into the zones in which it falls.  Repeatedly
-        * take the segment in which the remaining hole starts, round it
-        * to the end of that zone.
-        */
-       memset(zones, 0, MAX_NR_ZONES * sizeof(long));
-       while (cstart < cend) {
-               if (cstart < max_dma) {
-                       z = ZONE_DMA;
-                       rend = (cend < max_dma)? cend : max_dma;
-
-               } else if (cstart < max_low_pfn) {
-                       z = ZONE_NORMAL;
-                       rend = (cend < max_low_pfn)? cend : max_low_pfn;
-
-               } else {
-                       z = ZONE_HIGHMEM;
-                       rend = cend;
-               }
-               zones[z] += rend - cstart;
-               cstart = rend;
-       }
-}
-
 /*
  * The SRAT table always lists ascending addresses, so can always
  * assume that the first "start" address that you see is the real
@@ -220,7 +177,6 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 
        memset(pxm_bitmap, 0, sizeof(pxm_bitmap));      /* init proximity domain bitmap */
        memset(node_memory_chunk, 0, sizeof(node_memory_chunk));
-       memset(zholes_size, 0, sizeof(zholes_size));
 
        num_memory_chunks = 0;
        while (p < end) {
@@ -284,6 +240,7 @@ static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
                printk("chunk %d nid %d start_pfn %08lx end_pfn %08lx\n",
                       j, chunk->nid, chunk->start_pfn, chunk->end_pfn);
                node_read_chunk(chunk->nid, chunk);
+               add_active_range(chunk->nid, chunk->start_pfn, chunk->end_pfn);
        }
  
        for_each_online_node(nid) {
@@ -392,57 +349,7 @@ int __init get_memcfg_from_srat(void)
                return acpi20_parse_srat((struct acpi_table_srat *)header);
        }
 out_err:
+       remove_all_active_ranges();
        printk("failed to get NUMA memory information from SRAT table\n");
        return 0;
 }
-
-/* For each node run the memory list to determine whether there are
- * any memory holes.  For each hole determine which ZONE they fall
- * into.
- *
- * NOTE#1: this requires knowledge of the zone boundries and so
- * _cannot_ be performed before those are calculated in setup_memory.
- * 
- * NOTE#2: we rely on the fact that the memory chunks are ordered by
- * start pfn number during setup.
- */
-static void __init get_zholes_init(void)
-{
-       int nid;
-       int c;
-       int first;
-       unsigned long end = 0;
-
-       for_each_online_node(nid) {
-               first = 1;
-               for (c = 0; c < num_memory_chunks; c++){
-                       if (node_memory_chunk[c].nid == nid) {
-                               if (first) {
-                                       end = node_memory_chunk[c].end_pfn;
-                                       first = 0;
-
-                               } else {
-                                       /* Record any gap between this chunk
-                                        * and the previous chunk on this node
-                                        * against the zones it spans.
-                                        */
-                                       chunk_to_zones(end,
-                                               node_memory_chunk[c].start_pfn,
-                                               &zholes_size[nid * MAX_NR_ZONES]);
-                               }
-                       }
-               }
-       }
-}
-
-unsigned long * __init get_zholes_size(int nid)
-{
-       if (!zholes_size_init) {
-               zholes_size_init++;
-               get_zholes_init();
-       }
-       if (nid >= MAX_NUMNODES || !node_online(nid))
-               printk("%s: nid = %d is invalid/offline. num_online_nodes = %d",
-                      __FUNCTION__, nid, num_online_nodes());
-       return &zholes_size[nid * MAX_NR_ZONES];
-}
diff --git a/arch/i386/kernel/stacktrace.c b/arch/i386/kernel/stacktrace.c
deleted file mode 100644 (file)
index e62a037..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * arch/i386/kernel/stacktrace.c
- *
- * Stack trace management functions
- *
- *  Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- */
-#include <linux/sched.h>
-#include <linux/stacktrace.h>
-
-static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
-{
-       return  p > (void *)tinfo &&
-               p < (void *)tinfo + THREAD_SIZE - 3;
-}
-
-/*
- * Save stack-backtrace addresses into a stack_trace buffer:
- */
-static inline unsigned long
-save_context_stack(struct stack_trace *trace, unsigned int skip,
-                  struct thread_info *tinfo, unsigned long *stack,
-                  unsigned long ebp)
-{
-       unsigned long addr;
-
-#ifdef CONFIG_FRAME_POINTER
-       while (valid_stack_ptr(tinfo, (void *)ebp)) {
-               addr = *(unsigned long *)(ebp + 4);
-               if (!skip)
-                       trace->entries[trace->nr_entries++] = addr;
-               else
-                       skip--;
-               if (trace->nr_entries >= trace->max_entries)
-                       break;
-               /*
-                * break out of recursive entries (such as
-                * end_of_stack_stop_unwind_function):
-                */
-               if (ebp == *(unsigned long *)ebp)
-                       break;
-
-               ebp = *(unsigned long *)ebp;
-       }
-#else
-       while (valid_stack_ptr(tinfo, stack)) {
-               addr = *stack++;
-               if (__kernel_text_address(addr)) {
-                       if (!skip)
-                               trace->entries[trace->nr_entries++] = addr;
-                       else
-                               skip--;
-                       if (trace->nr_entries >= trace->max_entries)
-                               break;
-               }
-       }
-#endif
-
-       return ebp;
-}
-
-/*
- * Save stack-backtrace addresses into a stack_trace buffer.
- * If all_contexts is set, all contexts (hardirq, softirq and process)
- * are saved. If not set then only the current context is saved.
- */
-void save_stack_trace(struct stack_trace *trace,
-                     struct task_struct *task, int all_contexts,
-                     unsigned int skip)
-{
-       unsigned long ebp;
-       unsigned long *stack = &ebp;
-
-       WARN_ON(trace->nr_entries || !trace->max_entries);
-
-       if (!task || task == current) {
-               /* Grab ebp right from our regs: */
-               asm ("movl %%ebp, %0" : "=r" (ebp));
-       } else {
-               /* ebp is the last reg pushed by switch_to(): */
-               ebp = *(unsigned long *) task->thread.esp;
-       }
-
-       while (1) {
-               struct thread_info *context = (struct thread_info *)
-                               ((unsigned long)stack & (~(THREAD_SIZE - 1)));
-
-               ebp = save_context_stack(trace, skip, context, stack, ebp);
-               stack = (unsigned long *)context->previous_esp;
-               if (!all_contexts || !stack ||
-                               trace->nr_entries >= trace->max_entries)
-                       break;
-               trace->entries[trace->nr_entries++] = ULONG_MAX;
-               if (trace->nr_entries >= trace->max_entries)
-                       break;
-       }
-}
-
index dd63d4775398a301341063458a19d1a24e202279..7e639f78b0b9f274ea055ef42275506b262a769c 100644 (file)
@@ -317,3 +317,4 @@ ENTRY(sys_call_table)
        .long sys_tee                   /* 315 */
        .long sys_vmsplice
        .long sys_move_pages
+       .long sys_getcpu
index 1302e4ab3c4f6789a74de1fb142df914f3164baa..86944acfb647228186544f2c8ce3375b9c5d6efe 100644 (file)
@@ -130,18 +130,33 @@ static int set_rtc_mmss(unsigned long nowtime)
 
 int timer_ack;
 
-#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
 unsigned long profile_pc(struct pt_regs *regs)
 {
        unsigned long pc = instruction_pointer(regs);
 
-       if (!user_mode_vm(regs) && in_lock_functions(pc))
+#ifdef CONFIG_SMP
+       if (!user_mode_vm(regs) && 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;
+               /* Return address is either directly at stack pointer
+                  or above a saved eflags. Eflags has bits 22-31 zero,
+                  kernel addresses don't. */
+               if (sp[0] >> 22)
+                       return sp[0];
+               if (sp[1] >> 22)
+                       return sp[1];
+#endif
+       }
+#endif
        return pc;
 }
 EXPORT_SYMBOL(profile_pc);
-#endif
 
 /*
  * This is the same as the above, except we _also_ save the current
index e2e281d4bcc80ee7bc3b090e75914606231e6224..07d6da36a8253f39bbce04e90ab4edc0ece8aed4 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/nodemask.h>
+#include <linux/mmzone.h>
 #include <asm/cpu.h>
 
 static struct i386_cpu cpu_devices[NR_CPUS];
@@ -55,34 +56,18 @@ EXPORT_SYMBOL(arch_register_cpu);
 EXPORT_SYMBOL(arch_unregister_cpu);
 #endif /*CONFIG_HOTPLUG_CPU*/
 
-
-
-#ifdef CONFIG_NUMA
-#include <linux/mmzone.h>
-
 static int __init topology_init(void)
 {
        int i;
 
+#ifdef CONFIG_NUMA
        for_each_online_node(i)
                register_one_node(i);
+#endif /* CONFIG_NUMA */
 
        for_each_present_cpu(i)
                arch_register_cpu(i);
        return 0;
 }
 
-#else /* !CONFIG_NUMA */
-
-static int __init topology_init(void)
-{
-       int i;
-
-       for_each_present_cpu(i)
-               arch_register_cpu(i);
-       return 0;
-}
-
-#endif /* CONFIG_NUMA */
-
 subsys_initcall(topology_init);
index 4fcc6690be9923821369198c1d815995633677c9..a13037fe0ee383dc0088893af946ab5eb42bfd0e 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/kprobes.h>
 #include <linux/kexec.h>
 #include <linux/unwind.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_EISA
 #include <linux/ioport.h>
@@ -40,7 +41,6 @@
 
 #include <asm/processor.h>
 #include <asm/system.h>
-#include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/atomic.h>
 #include <asm/debugreg.h>
@@ -51,6 +51,7 @@
 #include <asm/smp.h>
 #include <asm/arch_hooks.h>
 #include <asm/kdebug.h>
+#include <asm/stacktrace.h>
 
 #include <linux/module.h>
 
@@ -118,26 +119,16 @@ static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
                p < (void *)tinfo + THREAD_SIZE - 3;
 }
 
-/*
- * Print one address/symbol entries per line.
- */
-static inline void print_addr_and_symbol(unsigned long addr, char *log_lvl)
-{
-       printk(" [<%08lx>] ", addr);
-
-       print_symbol("%s\n", addr);
-}
-
 static inline unsigned long print_context_stack(struct thread_info *tinfo,
                                unsigned long *stack, unsigned long ebp,
-                               char *log_lvl)
+                               struct stacktrace_ops *ops, void *data)
 {
        unsigned long addr;
 
 #ifdef CONFIG_FRAME_POINTER
        while (valid_stack_ptr(tinfo, (void *)ebp)) {
                addr = *(unsigned long *)(ebp + 4);
-               print_addr_and_symbol(addr, log_lvl);
+               ops->address(data, addr);
                /*
                 * break out of recursive entries (such as
                 * end_of_stack_stop_unwind_function):
@@ -150,30 +141,37 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
        while (valid_stack_ptr(tinfo, stack)) {
                addr = *stack++;
                if (__kernel_text_address(addr))
-                       print_addr_and_symbol(addr, log_lvl);
+                       ops->address(data, addr);
        }
 #endif
        return ebp;
 }
 
+struct ops_and_data {
+       struct stacktrace_ops *ops;
+       void *data;
+};
+
 static asmlinkage int
-show_trace_unwind(struct unwind_frame_info *info, void *log_lvl)
+dump_trace_unwind(struct unwind_frame_info *info, void *data)
 {
+       struct ops_and_data *oad = (struct ops_and_data *)data;
        int n = 0;
 
        while (unwind(info) == 0 && UNW_PC(info)) {
                n++;
-               print_addr_and_symbol(UNW_PC(info), log_lvl);
+               oad->ops->address(oad->data, UNW_PC(info));
                if (arch_unw_user_mode(info))
                        break;
        }
        return n;
 }
 
-static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
-                              unsigned long *stack, char *log_lvl)
+void dump_trace(struct task_struct *task, struct pt_regs *regs,
+               unsigned long *stack,
+               struct stacktrace_ops *ops, void *data)
 {
-       unsigned long ebp;
+       unsigned long ebp = 0;
 
        if (!task)
                task = current;
@@ -181,54 +179,116 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
        if (call_trace >= 0) {
                int unw_ret = 0;
                struct unwind_frame_info info;
+               struct ops_and_data oad = { .ops = ops, .data = data };
 
                if (regs) {
                        if (unwind_init_frame_info(&info, task, regs) == 0)
-                               unw_ret = show_trace_unwind(&info, log_lvl);
+                               unw_ret = dump_trace_unwind(&info, &oad);
                } else if (task == current)
-                       unw_ret = unwind_init_running(&info, show_trace_unwind, log_lvl);
+                       unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
                else {
                        if (unwind_init_blocked(&info, task) == 0)
-                               unw_ret = show_trace_unwind(&info, log_lvl);
+                               unw_ret = dump_trace_unwind(&info, &oad);
                }
                if (unw_ret > 0) {
                        if (call_trace == 1 && !arch_unw_user_mode(&info)) {
-                               print_symbol("DWARF2 unwinder stuck at %s\n",
+                               ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
                                             UNW_PC(&info));
                                if (UNW_SP(&info) >= PAGE_OFFSET) {
-                                       printk("Leftover inexact backtrace:\n");
+                                       ops->warning(data, "Leftover inexact backtrace:\n");
                                        stack = (void *)UNW_SP(&info);
+                                       if (!stack)
+                                               return;
+                                       ebp = UNW_FP(&info);
                                } else
-                                       printk("Full inexact backtrace again:\n");
+                                       ops->warning(data, "Full inexact backtrace again:\n");
                        } else if (call_trace >= 1)
                                return;
                        else
-                               printk("Full inexact backtrace again:\n");
+                               ops->warning(data, "Full inexact backtrace again:\n");
                } else
-                       printk("Inexact backtrace:\n");
+                       ops->warning(data, "Inexact backtrace:\n");
+       }
+       if (!stack) {
+               unsigned long dummy;
+               stack = &dummy;
+               if (task && task != current)
+                       stack = (unsigned long *)task->thread.esp;
        }
 
-       if (task == current) {
-               /* Grab ebp right from our regs */
-               asm ("movl %%ebp, %0" : "=r" (ebp) : );
-       } else {
-               /* ebp is the last reg pushed by switch_to */
-               ebp = *(unsigned long *) task->thread.esp;
+#ifdef CONFIG_FRAME_POINTER
+       if (!ebp) {
+               if (task == current) {
+                       /* Grab ebp right from our regs */
+                       asm ("movl %%ebp, %0" : "=r" (ebp) : );
+               } else {
+                       /* ebp is the last reg pushed by switch_to */
+                       ebp = *(unsigned long *) task->thread.esp;
+               }
        }
+#endif
 
        while (1) {
                struct thread_info *context;
                context = (struct thread_info *)
                        ((unsigned long)stack & (~(THREAD_SIZE - 1)));
-               ebp = print_context_stack(context, stack, ebp, log_lvl);
+               ebp = print_context_stack(context, stack, ebp, ops, data);
+               /* Should be after the line below, but somewhere
+                  in early boot context comes out corrupted and we
+                  can't reference it -AK */
+               if (ops->stack(data, "IRQ") < 0)
+                       break;
                stack = (unsigned long*)context->previous_esp;
                if (!stack)
                        break;
-               printk("%s =======================\n", log_lvl);
        }
 }
+EXPORT_SYMBOL(dump_trace);
+
+static void
+print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+       printk(data);
+       print_symbol(msg, symbol);
+       printk("\n");
+}
+
+static void print_trace_warning(void *data, char *msg)
+{
+       printk("%s%s\n", (char *)data, msg);
+}
+
+static int print_trace_stack(void *data, char *name)
+{
+       return 0;
+}
+
+/*
+ * Print one address/symbol entries per line.
+ */
+static void print_trace_address(void *data, unsigned long addr)
+{
+       printk("%s [<%08lx>] ", (char *)data, addr);
+       print_symbol("%s\n", addr);
+}
+
+static struct stacktrace_ops print_trace_ops = {
+       .warning = print_trace_warning,
+       .warning_symbol = print_trace_warning_symbol,
+       .stack = print_trace_stack,
+       .address = print_trace_address,
+};
+
+static void
+show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
+                  unsigned long * stack, char *log_lvl)
+{
+       dump_trace(task, regs, stack, &print_trace_ops, log_lvl);
+       printk("%s =======================\n", log_lvl);
+}
 
-void show_trace(struct task_struct *task, struct pt_regs *regs, unsigned long * stack)
+void show_trace(struct task_struct *task, struct pt_regs *regs,
+               unsigned long * stack)
 {
        show_trace_log_lvl(task, regs, stack, "");
 }
@@ -291,8 +351,9 @@ void show_registers(struct pt_regs *regs)
                ss = regs->xss & 0xffff;
        }
        print_modules();
-       printk(KERN_EMERG "CPU:    %d\nEIP:    %04x:[<%08lx>]    %s VLI\n"
-                       "EFLAGS: %08lx   (%s %.*s) \n",
+       printk(KERN_EMERG "CPU:    %d\n"
+               KERN_EMERG "EIP:    %04x:[<%08lx>]    %s VLI\n"
+               KERN_EMERG "EFLAGS: %08lx   (%s %.*s)\n",
                smp_processor_id(), 0xffff & regs->xcs, regs->eip,
                print_tainted(), regs->eflags, system_utsname.release,
                (int)strcspn(system_utsname.version, " "),
@@ -348,7 +409,7 @@ static void handle_BUG(struct pt_regs *regs)
 
        if (eip < PAGE_OFFSET)
                return;
-       if (__get_user(ud2, (unsigned short __user *)eip))
+       if (probe_kernel_address((unsigned short __user *)eip, ud2))
                return;
        if (ud2 != 0x0b0f)
                return;
@@ -361,7 +422,8 @@ static void handle_BUG(struct pt_regs *regs)
                char *file;
                char c;
 
-               if (__get_user(line, (unsigned short __user *)(eip + 2)))
+               if (probe_kernel_address((unsigned short __user *)(eip + 2),
+                                       line))
                        break;
                if (__get_user(file, (char * __user *)(eip + 4)) ||
                    (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
@@ -634,18 +696,24 @@ gp_in_kernel:
        }
 }
 
-static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
+static __kprobes void
+mem_parity_error(unsigned char reason, struct pt_regs * regs)
 {
-       printk(KERN_EMERG "Uhhuh. NMI received. Dazed and confused, but trying "
-                       "to continue\n");
+       printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+               "CPU %d.\n", reason, smp_processor_id());
        printk(KERN_EMERG "You probably have a hardware problem with your RAM "
                        "chips\n");
+       if (panic_on_unrecovered_nmi)
+                panic("NMI: Not continuing");
+
+       printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
 
        /* Clear and disable the memory parity error line. */
        clear_mem_error(reason);
 }
 
-static void io_check_error(unsigned char reason, struct pt_regs * regs)
+static __kprobes void
+io_check_error(unsigned char reason, struct pt_regs * regs)
 {
        unsigned long i;
 
@@ -661,7 +729,8 @@ static void io_check_error(unsigned char reason, struct pt_regs * regs)
        outb(reason, 0x61);
 }
 
-static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+static __kprobes void
+unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
 {
 #ifdef CONFIG_MCA
        /* Might actually be able to figure out what the guilty party
@@ -671,15 +740,18 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
                return;
        }
 #endif
-       printk("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n",
-               reason, smp_processor_id());
-       printk("Dazed and confused, but trying to continue\n");
-       printk("Do you have a strange power saving mode enabled?\n");
+       printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
+               "CPU %d.\n", reason, smp_processor_id());
+       printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+       if (panic_on_unrecovered_nmi)
+                panic("NMI: Not continuing");
+
+       printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
 }
 
 static DEFINE_SPINLOCK(nmi_print_lock);
 
-void die_nmi (struct pt_regs *regs, const char *msg)
+void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
 {
        if (notify_die(DIE_NMIWATCHDOG, msg, regs, 0, 2, SIGINT) ==
            NOTIFY_STOP)
@@ -711,7 +783,7 @@ void die_nmi (struct pt_regs *regs, const char *msg)
        do_exit(SIGSEGV);
 }
 
-static void default_do_nmi(struct pt_regs * regs)
+static __kprobes void default_do_nmi(struct pt_regs * regs)
 {
        unsigned char reason = 0;
 
@@ -728,12 +800,12 @@ static void default_do_nmi(struct pt_regs * regs)
                 * Ok, so this is none of the documented NMI sources,
                 * so it must be the NMI watchdog.
                 */
-               if (nmi_watchdog) {
-                       nmi_watchdog_tick(regs);
+               if (nmi_watchdog_tick(regs, reason))
                        return;
-               }
+               if (!do_nmi_callback(regs, smp_processor_id()))
 #endif
-               unknown_nmi_error(reason, regs);
+                       unknown_nmi_error(reason, regs);
+
                return;
        }
        if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
@@ -749,14 +821,7 @@ static void default_do_nmi(struct pt_regs * regs)
        reassert_nmi();
 }
 
-static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
-{
-       return 0;
-}
-static nmi_callback_t nmi_callback = dummy_nmi_callback;
-fastcall void do_nmi(struct pt_regs * regs, long error_code)
+fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code)
 {
        int cpu;
 
@@ -766,25 +831,11 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code)
 
        ++nmi_count(cpu);
 
-       if (!rcu_dereference(nmi_callback)(regs, cpu))
-               default_do_nmi(regs);
+       default_do_nmi(regs);
 
        nmi_exit();
 }
 
-void set_nmi_callback(nmi_callback_t callback)
-{
-       vmalloc_sync_all();
-       rcu_assign_pointer(nmi_callback, callback);
-}
-EXPORT_SYMBOL_GPL(set_nmi_callback);
-
-void unset_nmi_callback(void)
-{
-       nmi_callback = dummy_nmi_callback;
-}
-EXPORT_SYMBOL_GPL(unset_nmi_callback);
-
 #ifdef CONFIG_KPROBES
 fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code)
 {
@@ -1124,20 +1175,6 @@ void __init trap_init_f00f_bug(void)
 }
 #endif
 
-#define _set_gate(gate_addr,type,dpl,addr,seg) \
-do { \
-  int __d0, __d1; \
-  __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
-       "movw %4,%%dx\n\t" \
-       "movl %%eax,%0\n\t" \
-       "movl %%edx,%1" \
-       :"=m" (*((long *) (gate_addr))), \
-        "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
-       :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
-        "3" ((char *) (addr)),"2" ((seg) << 16)); \
-} while (0)
-
-
 /*
  * This needs to use 'idt_table' rather than 'idt', and
  * thus use the _nonmapped_ version of the IDT, as the
@@ -1146,7 +1183,7 @@ do { \
  */
 void set_intr_gate(unsigned int n, void *addr)
 {
-       _set_gate(idt_table+n,14,0,addr,__KERNEL_CS);
+       _set_gate(n, DESCTYPE_INT, addr, __KERNEL_CS);
 }
 
 /*
@@ -1154,22 +1191,22 @@ void set_intr_gate(unsigned int n, void *addr)
  */
 static inline void set_system_intr_gate(unsigned int n, void *addr)
 {
-       _set_gate(idt_table+n, 14, 3, addr, __KERNEL_CS);
+       _set_gate(n, DESCTYPE_INT | DESCTYPE_DPL3, addr, __KERNEL_CS);
 }
 
 static void __init set_trap_gate(unsigned int n, void *addr)
 {
-       _set_gate(idt_table+n,15,0,addr,__KERNEL_CS);
+       _set_gate(n, DESCTYPE_TRAP, addr, __KERNEL_CS);
 }
 
 static void __init set_system_gate(unsigned int n, void *addr)
 {
-       _set_gate(idt_table+n,15,3,addr,__KERNEL_CS);
+       _set_gate(n, DESCTYPE_TRAP | DESCTYPE_DPL3, addr, __KERNEL_CS);
 }
 
 static void __init set_task_gate(unsigned int n, unsigned int gdt_entry)
 {
-       _set_gate(idt_table+n,5,0,0,(gdt_entry<<3));
+       _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3));
 }
 
 
index 7e0d8dab207519f7625b722327ce06e531f077c5..b8fa0a8b2e4733170d0b72cff576d7ddb8c750cd 100644 (file)
@@ -192,7 +192,7 @@ int recalibrate_cpu_khz(void)
 
 EXPORT_SYMBOL(recalibrate_cpu_khz);
 
-void tsc_init(void)
+void __init tsc_init(void)
 {
        if (!cpu_has_tsc || tsc_disable)
                return;
index 914933e9ec3d29847e8a1b59b08902c87146e3cf..d86a548b8d543af5958961ccce281b83b3e15d6c 100644 (file)
@@ -4,6 +4,6 @@
 
 
 lib-y = checksum.o delay.o usercopy.o getuser.o putuser.o memcpy.o strstr.o \
-       bitops.o
+       bitops.o semaphore.o
 
 lib-$(CONFIG_X86_USE_3DNOW) += mmx.o
diff --git a/arch/i386/lib/semaphore.S b/arch/i386/lib/semaphore.S
new file mode 100644 (file)
index 0000000..01f80b5
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * i386 semaphore implementation.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * Portions Copyright 1999 Red Hat, 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.
+ *
+ * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/rwlock.h>
+#include <asm/alternative-asm.i>
+#include <asm/frame.i>
+#include <asm/dwarf2.h>
+
+/*
+ * The semaphore operations have a special calling sequence that
+ * allow us to do a simpler in-line version of them. These routines
+ * need to convert that sequence back into the C sequence when
+ * there is contention on the semaphore.
+ *
+ * %eax contains the semaphore pointer on entry. Save the C-clobbered
+ * registers (%eax, %edx and %ecx) except %eax whish is either a return
+ * value or just clobbered..
+ */
+       .section .sched.text
+ENTRY(__down_failed)
+       CFI_STARTPROC
+       FRAME
+       pushl %edx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET edx,0
+       pushl %ecx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ecx,0
+       call __down
+       popl %ecx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE ecx
+       popl %edx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE edx
+       ENDFRAME
+       ret
+       CFI_ENDPROC
+       END(__down_failed)
+
+ENTRY(__down_failed_interruptible)
+       CFI_STARTPROC
+       FRAME
+       pushl %edx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET edx,0
+       pushl %ecx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ecx,0
+       call __down_interruptible
+       popl %ecx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE ecx
+       popl %edx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE edx
+       ENDFRAME
+       ret
+       CFI_ENDPROC
+       END(__down_failed_interruptible)
+
+ENTRY(__down_failed_trylock)
+       CFI_STARTPROC
+       FRAME
+       pushl %edx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET edx,0
+       pushl %ecx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ecx,0
+       call __down_trylock
+       popl %ecx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE ecx
+       popl %edx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE edx
+       ENDFRAME
+       ret
+       CFI_ENDPROC
+       END(__down_failed_trylock)
+
+ENTRY(__up_wakeup)
+       CFI_STARTPROC
+       FRAME
+       pushl %edx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET edx,0
+       pushl %ecx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ecx,0
+       call __up
+       popl %ecx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE ecx
+       popl %edx
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE edx
+       ENDFRAME
+       ret
+       CFI_ENDPROC
+       END(__up_wakeup)
+
+/*
+ * rw spinlock fallbacks
+ */
+#ifdef CONFIG_SMP
+ENTRY(__write_lock_failed)
+       CFI_STARTPROC simple
+       FRAME
+2:     LOCK_PREFIX
+       addl    $ RW_LOCK_BIAS,(%eax)
+1:     rep; nop
+       cmpl    $ RW_LOCK_BIAS,(%eax)
+       jne     1b
+       LOCK_PREFIX
+       subl    $ RW_LOCK_BIAS,(%eax)
+       jnz     2b
+       ENDFRAME
+       ret
+       CFI_ENDPROC
+       END(__write_lock_failed)
+
+ENTRY(__read_lock_failed)
+       CFI_STARTPROC
+       FRAME
+2:     LOCK_PREFIX
+       incl    (%eax)
+1:     rep; nop
+       cmpl    $1,(%eax)
+       js      1b
+       LOCK_PREFIX
+       decl    (%eax)
+       js      2b
+       ENDFRAME
+       ret
+       CFI_ENDPROC
+       END(__read_lock_failed)
+
+#endif
+
+/* Fix up special calling conventions */
+ENTRY(call_rwsem_down_read_failed)
+       CFI_STARTPROC
+       push %ecx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ecx,0
+       push %edx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET edx,0
+       call rwsem_down_read_failed
+       pop %edx
+       CFI_ADJUST_CFA_OFFSET -4
+       pop %ecx
+       CFI_ADJUST_CFA_OFFSET -4
+       ret
+       CFI_ENDPROC
+       END(call_rwsem_down_read_failed)
+
+ENTRY(call_rwsem_down_write_failed)
+       CFI_STARTPROC
+       push %ecx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ecx,0
+       calll rwsem_down_write_failed
+       pop %ecx
+       CFI_ADJUST_CFA_OFFSET -4
+       ret
+       CFI_ENDPROC
+       END(call_rwsem_down_write_failed)
+
+ENTRY(call_rwsem_wake)
+       CFI_STARTPROC
+       decw %dx    /* do nothing if still outstanding active readers */
+       jnz 1f
+       push %ecx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ecx,0
+       call rwsem_wake
+       pop %ecx
+       CFI_ADJUST_CFA_OFFSET -4
+1:     ret
+       CFI_ENDPROC
+       END(call_rwsem_wake)
+
+/* Fix up special calling conventions */
+ENTRY(call_rwsem_downgrade_wake)
+       CFI_STARTPROC
+       push %ecx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ecx,0
+       push %edx
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET edx,0
+       call rwsem_downgrade_wake
+       pop %edx
+       CFI_ADJUST_CFA_OFFSET -4
+       pop %ecx
+       CFI_ADJUST_CFA_OFFSET -4
+       ret
+       CFI_ENDPROC
+       END(call_rwsem_downgrade_wake)
+
index ef7a6e6fcb9f0a834e67a9d4608707f98cd5e027..33d9f93557badd2d1a466ba5268cf81665904e67 100644 (file)
@@ -5,6 +5,7 @@
 #define APIC_DEFINITION 1
 #include <linux/threads.h>
 #include <linux/cpumask.h>
+#include <asm/smp.h>
 #include <asm/mpspec.h>
 #include <asm/genapic.h>
 #include <asm/fixmap.h>
index 845cdd0b359350f4c6e860f9287999038c7358f7..aa144d82334de969c921f70b04ca1fb41fc46fc5 100644 (file)
@@ -4,6 +4,7 @@
 #define APIC_DEFINITION 1
 #include <linux/threads.h>
 #include <linux/cpumask.h>
+#include <asm/smp.h>
 #include <asm/mpspec.h>
 #include <asm/genapic.h>
 #include <asm/fixmap.h>
index bcd1bcfaa7238e9ad546c7191d506e0329e8f578..94b1fd9cbe3cdaef7aaed0b5dcb84bfcff12d7a4 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/ctype.h>
 #include <linux/init.h>
+#include <linux/errno.h>
 #include <asm/fixmap.h>
 #include <asm/mpspec.h>
 #include <asm/apicdef.h>
@@ -29,7 +30,24 @@ struct genapic *apic_probe[] __initdata = {
        NULL,
 };
 
-static int cmdline_apic;
+static int cmdline_apic __initdata;
+static int __init parse_apic(char *arg)
+{
+       int i;
+
+       if (!arg)
+               return -EINVAL;
+
+       for (i = 0; apic_probe[i]; i++) {
+               if (!strcmp(apic_probe[i]->name, arg)) {
+                       genapic = apic_probe[i];
+                       cmdline_apic = 1;
+                       return 0;
+               }
+       }
+       return -ENOENT;
+}
+early_param("apic", parse_apic);
 
 void __init generic_bigsmp_probe(void)
 {
@@ -48,40 +66,20 @@ void __init generic_bigsmp_probe(void)
                }
 }
 
-void __init generic_apic_probe(char *command_line) 
+void __init generic_apic_probe(void)
 { 
-       char *s;
-       int i;
-       int changed = 0;
-
-       s = strstr(command_line, "apic=");
-       if (s && (s == command_line || isspace(s[-1]))) { 
-               char *p = strchr(s, ' '), old; 
-               if (!p)
-                       p = strchr(s, '\0'); 
-               old = *p; 
-               *p = 0; 
-               for (i = 0; !changed && apic_probe[i]; i++) {
-                       if (!strcmp(apic_probe[i]->name, s+5)) { 
-                               changed = 1;
+       if (!cmdline_apic) {
+               int i;
+               for (i = 0; apic_probe[i]; i++) {
+                       if (apic_probe[i]->probe()) {
                                genapic = apic_probe[i];
+                               break;
                        }
                }
-               if (!changed)
-                       printk(KERN_ERR "Unknown genapic `%s' specified.\n", s);
-               *p = old;
-               cmdline_apic = changed;
-       } 
-       for (i = 0; !changed && apic_probe[i]; i++) { 
-               if (apic_probe[i]->probe()) {
-                       changed = 1;
-                       genapic = apic_probe[i]; 
-               } 
+               /* Not visible without early console */
+               if (!apic_probe[i])
+                       panic("Didn't find an APIC driver");
        }
-       /* Not visible without early console */ 
-       if (!changed) 
-               panic("Didn't find an APIC driver"); 
-
        printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
 } 
 
@@ -119,7 +117,9 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
        return 0;       
 }
 
+#ifdef CONFIG_SMP
 int hard_smp_processor_id(void)
 {
        return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID));
 }
+#endif
index b73501ddd653a9fed0be28c112a1a1c351707de2..f7e5d66648dc1ee16d30981e49847ffc509077b6 100644 (file)
@@ -4,6 +4,7 @@
 #define APIC_DEFINITION 1
 #include <linux/threads.h>
 #include <linux/cpumask.h>
+#include <asm/smp.h>
 #include <asm/mpspec.h>
 #include <asm/genapic.h>
 #include <asm/fixmap.h>
index fb5d8b747de441ef3dbe5e94eaecab6da6071e50..51e3739dd22700f13a28a0627163fcc6bfb94bb0 100644 (file)
@@ -157,21 +157,6 @@ static void __init find_max_pfn_node(int nid)
                BUG();
 }
 
-/* Find the owning node for a pfn. */
-int early_pfn_to_nid(unsigned long pfn)
-{
-       int nid;
-
-       for_each_node(nid) {
-               if (node_end_pfn[nid] == 0)
-                       break;
-               if (node_start_pfn[nid] <= pfn && node_end_pfn[nid] >= pfn)
-                       return nid;
-       }
-
-       return 0;
-}
-
 /* 
  * Allocate memory for the pg_data_t for this node via a crude pre-bootmem
  * method.  For node zero take this from the bottom of memory, for
@@ -227,6 +212,8 @@ static unsigned long calculate_numa_remap_pages(void)
        unsigned long pfn;
 
        for_each_online_node(nid) {
+               unsigned old_end_pfn = node_end_pfn[nid];
+
                /*
                 * The acpi/srat node info can show hot-add memroy zones
                 * where memory could be added but not currently present.
@@ -276,6 +263,7 @@ static unsigned long calculate_numa_remap_pages(void)
 
                node_end_pfn[nid] -= size;
                node_remap_start_pfn[nid] = node_end_pfn[nid];
+               shrink_active_range(nid, old_end_pfn, node_end_pfn[nid]);
        }
        printk("Reserving total of %ld pages for numa KVA remap\n",
                        reserve_pages);
@@ -322,6 +310,11 @@ unsigned long __init setup_memory(void)
                highstart_pfn = system_max_low_pfn;
        printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
               pages_to_mb(highend_pfn - highstart_pfn));
+       num_physpages = highend_pfn;
+       high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
+#else
+       num_physpages = system_max_low_pfn;
+       high_memory = (void *) __va(system_max_low_pfn * PAGE_SIZE - 1) + 1;
 #endif
        printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
                        pages_to_mb(system_max_low_pfn));
@@ -364,45 +357,22 @@ void __init numa_kva_reserve(void)
 void __init zone_sizes_init(void)
 {
        int nid;
-
-
-       for_each_online_node(nid) {
-               unsigned long zones_size[MAX_NR_ZONES] = {0, };
-               unsigned long *zholes_size;
-               unsigned int max_dma;
-
-               unsigned long low = max_low_pfn;
-               unsigned long start = node_start_pfn[nid];
-               unsigned long high = node_end_pfn[nid];
-
-               max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-
-               if (node_has_online_mem(nid)){
-                       if (start > low) {
-#ifdef CONFIG_HIGHMEM
-                               BUG_ON(start > high);
-                               zones_size[ZONE_HIGHMEM] = high - start;
-#endif
-                       } else {
-                               if (low < max_dma)
-                                       zones_size[ZONE_DMA] = low;
-                               else {
-                                       BUG_ON(max_dma > low);
-                                       BUG_ON(low > high);
-                                       zones_size[ZONE_DMA] = max_dma;
-                                       zones_size[ZONE_NORMAL] = low - max_dma;
-#ifdef CONFIG_HIGHMEM
-                                       zones_size[ZONE_HIGHMEM] = high - low;
-#endif
-                               }
-                       }
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+               virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT,
+               max_low_pfn,
+               highend_pfn
+       };
+
+       /* If SRAT has not registered memory, register it now */
+       if (find_max_pfn_with_active_regions() == 0) {
+               for_each_online_node(nid) {
+                       if (node_has_online_mem(nid))
+                               add_active_range(nid, node_start_pfn[nid],
+                                                       node_end_pfn[nid]);
                }
-
-               zholes_size = get_zholes_size(nid);
-
-               free_area_init_node(nid, NODE_DATA(nid), zones_size, start,
-                               zholes_size);
        }
+
+       free_area_init_nodes(max_zone_pfns);
        return;
 }
 
index de03c5430abc86a03b96d0326bd6ab3317d624b5..0ce4f22a2635fb6da5c80ffea658b6a49c0dcdf8 100644 (file)
@@ -11,7 +11,7 @@ int fixup_exception(struct pt_regs *regs)
        const struct exception_table_entry *fixup;
 
 #ifdef CONFIG_PNPBIOS
-       if (unlikely((regs->xcs & ~15) == (GDT_ENTRY_PNPBIOS_BASE << 3)))
+       if (unlikely(SEGMENT_IS_PNP_CODE(regs->xcs)))
        {
                extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
                extern u32 pnp_bios_is_utter_crap;
index f7279468323a62cef22984f3e81707eaa6a93b4b..5e17a3f43b41ba89c15b17e7390f04dc730ada64 100644 (file)
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 #include <asm/kdebug.h>
+#include <asm/segment.h>
 
 extern void die(const char *,struct pt_regs *,long);
 
-#ifdef CONFIG_KPROBES
-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+
 int register_page_fault_notifier(struct notifier_block *nb)
 {
        vmalloc_sync_all();
        return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
 }
+EXPORT_SYMBOL_GPL(register_page_fault_notifier);
 
 int unregister_page_fault_notifier(struct notifier_block *nb)
 {
        return atomic_notifier_chain_unregister(&notify_page_fault_chain, 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)
@@ -55,14 +58,6 @@ static inline int notify_page_fault(enum die_val val, const char *str,
        };
        return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
 }
-#else
-static inline int notify_page_fault(enum die_val val, const char *str,
-                       struct pt_regs *regs, long err, int trap, int sig)
-{
-       return NOTIFY_DONE;
-}
-#endif
-
 
 /*
  * Unlock any spinlocks which will prevent us from getting the
@@ -119,10 +114,10 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
        }
 
        /* The standard kernel/user address space limit. */
-       *eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg;
+       *eip_limit = user_mode(regs) ? USER_DS.seg : KERNEL_DS.seg;
        
        /* By far the most common cases. */
-       if (likely(seg == __USER_CS || seg == __KERNEL_CS))
+       if (likely(SEGMENT_IS_FLAT_CODE(seg)))
                return eip;
 
        /* Check the segment exists, is within the current LDT/GDT size,
@@ -436,11 +431,7 @@ good_area:
        write = 0;
        switch (error_code & 3) {
                default:        /* 3: write, present */
-#ifdef TEST_VERIFY_AREA
-                       if (regs->cs == KERNEL_CS)
-                               printk("WP fault at %08lx\n", regs->eip);
-#endif
-                       /* fall through */
+                               /* fall through */
                case 2:         /* write, not present */
                        if (!(vma->vm_flags & VM_WRITE))
                                goto bad_area;
index b6eb4dcb8777e60e173985b2ae67d3be5bc3a058..ba44000b9069f5376d64304fafdf43ddcd4987f7 100644 (file)
@@ -54,7 +54,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
        enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
-       if (vaddr < FIXADDR_START) { // FIXME
+       if (vaddr >= PAGE_OFFSET && vaddr < (unsigned long)high_memory) {
                dec_preempt_count();
                preempt_check_resched();
                return;
index efd0bcdac65da65264c19e6949c24dc4ab832350..4a5a914b34321bcc69b714ca17223b08bc898edb 100644 (file)
@@ -435,16 +435,22 @@ u64 __supported_pte_mask __read_mostly = ~_PAGE_NX;
  * on      Enable
  * off     Disable
  */
-void __init noexec_setup(const char *str)
+static int __init noexec_setup(char *str)
 {
-       if (!strncmp(str, "on",2) && cpu_has_nx) {
-               __supported_pte_mask |= _PAGE_NX;
-               disable_nx = 0;
-       } else if (!strncmp(str,"off",3)) {
+       if (!str || !strcmp(str, "on")) {
+               if (cpu_has_nx) {
+                       __supported_pte_mask |= _PAGE_NX;
+                       disable_nx = 0;
+               }
+       } else if (!strcmp(str,"off")) {
                disable_nx = 1;
                __supported_pte_mask &= ~_PAGE_NX;
-       }
+       } else
+               return -EINVAL;
+
+       return 0;
 }
+early_param("noexec", noexec_setup);
 
 int nx_enabled = 0;
 #ifdef CONFIG_X86_PAE
@@ -552,18 +558,6 @@ static void __init test_wp_bit(void)
        }
 }
 
-static void __init set_max_mapnr_init(void)
-{
-#ifdef CONFIG_HIGHMEM
-       num_physpages = highend_pfn;
-#else
-       num_physpages = max_low_pfn;
-#endif
-#ifdef CONFIG_FLATMEM
-       max_mapnr = num_physpages;
-#endif
-}
-
 static struct kcore_list kcore_mem, kcore_vmalloc; 
 
 void __init mem_init(void)
@@ -590,14 +584,6 @@ void __init mem_init(void)
        }
 #endif
  
-       set_max_mapnr_init();
-
-#ifdef CONFIG_HIGHMEM
-       high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
-#else
-       high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
-#endif
-
        /* this will put all low memory onto the freelists */
        totalram_pages += free_all_bootmem();
 
index 5f8dc8a21bd7157e2fa9e40a6b18422fc0ed2c00..3700eef78743160787de152444c95eeaa03d93a9 100644 (file)
 #include <asm/nmi.h>
 #include <asm/msr.h>
 #include <asm/apic.h>
+#include <asm/kdebug.h>
  
 #include "op_counter.h"
 #include "op_x86_model.h"
+
 static struct op_x86_model_spec const * model;
 static struct op_msrs cpu_msrs[NR_CPUS];
 static unsigned long saved_lvtpc[NR_CPUS];
+
 static int nmi_start(void);
 static void nmi_stop(void);
 
@@ -82,13 +83,24 @@ static void exit_driverfs(void)
 #define exit_driverfs() do { } while (0)
 #endif /* CONFIG_PM */
 
-
-static int nmi_callback(struct pt_regs * regs, int cpu)
+static int profile_exceptions_notify(struct notifier_block *self,
+                                    unsigned long val, void *data)
 {
-       return model->check_ctrs(regs, &cpu_msrs[cpu]);
+       struct die_args *args = (struct die_args *)data;
+       int ret = NOTIFY_DONE;
+       int cpu = smp_processor_id();
+
+       switch(val) {
+       case DIE_NMI:
+               if (model->check_ctrs(args->regs, &cpu_msrs[cpu]))
+                       ret = NOTIFY_STOP;
+               break;
+       default:
+               break;
+       }
+       return ret;
 }
+
 static void nmi_cpu_save_registers(struct op_msrs * msrs)
 {
        unsigned int const nr_ctrs = model->num_counters;
@@ -98,15 +110,19 @@ static void nmi_cpu_save_registers(struct op_msrs * msrs)
        unsigned int i;
 
        for (i = 0; i < nr_ctrs; ++i) {
-               rdmsr(counters[i].addr,
-                       counters[i].saved.low,
-                       counters[i].saved.high);
+               if (counters[i].addr){
+                       rdmsr(counters[i].addr,
+                               counters[i].saved.low,
+                               counters[i].saved.high);
+               }
        }
  
        for (i = 0; i < nr_ctrls; ++i) {
-               rdmsr(controls[i].addr,
-                       controls[i].saved.low,
-                       controls[i].saved.high);
+               if (controls[i].addr){
+                       rdmsr(controls[i].addr,
+                               controls[i].saved.low,
+                               controls[i].saved.high);
+               }
        }
 }
 
@@ -170,27 +186,29 @@ static void nmi_cpu_setup(void * dummy)
        apic_write(APIC_LVTPC, APIC_DM_NMI);
 }
 
+static struct notifier_block profile_exceptions_nb = {
+       .notifier_call = profile_exceptions_notify,
+       .next = NULL,
+       .priority = 0
+};
 
 static int nmi_setup(void)
 {
+       int err=0;
+
        if (!allocate_msrs())
                return -ENOMEM;
 
-       /* We walk a thin line between law and rape here.
-        * We need to be careful to install our NMI handler
-        * without actually triggering any NMIs as this will
-        * break the core code horrifically.
-        */
-       if (reserve_lapic_nmi() < 0) {
+       if ((err = register_die_notifier(&profile_exceptions_nb))){
                free_msrs();
-               return -EBUSY;
+               return err;
        }
+
        /* We need to serialize save and setup for HT because the subset
         * of msrs are distinct for save and setup operations
         */
        on_each_cpu(nmi_save_registers, NULL, 0, 1);
        on_each_cpu(nmi_cpu_setup, NULL, 0, 1);
-       set_nmi_callback(nmi_callback);
        nmi_enabled = 1;
        return 0;
 }
@@ -205,15 +223,19 @@ static void nmi_restore_registers(struct op_msrs * msrs)
        unsigned int i;
 
        for (i = 0; i < nr_ctrls; ++i) {
-               wrmsr(controls[i].addr,
-                       controls[i].saved.low,
-                       controls[i].saved.high);
+               if (controls[i].addr){
+                       wrmsr(controls[i].addr,
+                               controls[i].saved.low,
+                               controls[i].saved.high);
+               }
        }
  
        for (i = 0; i < nr_ctrs; ++i) {
-               wrmsr(counters[i].addr,
-                       counters[i].saved.low,
-                       counters[i].saved.high);
+               if (counters[i].addr){
+                       wrmsr(counters[i].addr,
+                               counters[i].saved.low,
+                               counters[i].saved.high);
+               }
        }
 }
  
@@ -234,6 +256,7 @@ static void nmi_cpu_shutdown(void * dummy)
        apic_write(APIC_LVTPC, saved_lvtpc[cpu]);
        apic_write(APIC_LVTERR, v);
        nmi_restore_registers(msrs);
+       model->shutdown(msrs);
 }
 
  
@@ -241,8 +264,7 @@ static void nmi_shutdown(void)
 {
        nmi_enabled = 0;
        on_each_cpu(nmi_cpu_shutdown, NULL, 0, 1);
-       unset_nmi_callback();
-       release_lapic_nmi();
+       unregister_die_notifier(&profile_exceptions_nb);
        free_msrs();
 }
 
@@ -284,6 +306,14 @@ static int nmi_create_files(struct super_block * sb, struct dentry * root)
                struct dentry * dir;
                char buf[4];
  
+               /* quick little hack to _not_ expose a counter if it is not
+                * available for use.  This should protect userspace app.
+                * NOTE:  assumes 1:1 mapping here (that counters are organized
+                *        sequentially in their struct assignment).
+                */
+               if (unlikely(!avail_to_resrv_perfctr_nmi_bit(i)))
+                       continue;
+
                snprintf(buf,  sizeof(buf), "%d", i);
                dir = oprofilefs_mkdir(sb, root, buf);
                oprofilefs_create_ulong(sb, dir, "enabled", &counter_config[i].enabled); 
index 930a1127bb309e0ff9030384f452e1641d59ea96..abf0ba52a6359fd8dc12c2cae9b4137dcca8d6e7 100644 (file)
 #include <asm/nmi.h>
 #include <asm/apic.h>
 #include <asm/ptrace.h>
+#include <asm/kdebug.h>
  
-static int nmi_timer_callback(struct pt_regs * regs, int cpu)
+static int profile_timer_exceptions_notify(struct notifier_block *self,
+                                          unsigned long val, void *data)
 {
-       oprofile_add_sample(regs, 0);
-       return 1;
+       struct die_args *args = (struct die_args *)data;
+       int ret = NOTIFY_DONE;
+
+       switch(val) {
+       case DIE_NMI:
+               oprofile_add_sample(args->regs, 0);
+               ret = NOTIFY_STOP;
+               break;
+       default:
+               break;
+       }
+       return ret;
 }
 
+static struct notifier_block profile_timer_exceptions_nb = {
+       .notifier_call = profile_timer_exceptions_notify,
+       .next = NULL,
+       .priority = 0
+};
+
 static int timer_start(void)
 {
-       disable_timer_nmi_watchdog();
-       set_nmi_callback(nmi_timer_callback);
+       if (register_die_notifier(&profile_timer_exceptions_nb))
+               return 1;
        return 0;
 }
 
 
 static void timer_stop(void)
 {
-       enable_timer_nmi_watchdog();
-       unset_nmi_callback();
+       unregister_die_notifier(&profile_timer_exceptions_nb);
        synchronize_sched();  /* Allow already-started NMIs to complete. */
 }
 
 
 int __init op_nmi_timer_init(struct oprofile_operations * ops)
 {
-       extern int nmi_active;
-
-       if (nmi_active <= 0)
+       if ((nmi_watchdog != NMI_IO_APIC) || (atomic_read(&nmi_active) <= 0))
                return -ENODEV;
 
        ops->start = timer_start;
index 693bdea4a52b44f7a5800c599b9b8428f210664a..3057a19e4641be711836ed889ae8a48677de4cb7 100644 (file)
 #define NUM_COUNTERS 4
 #define NUM_CONTROLS 4
 
+#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, -(unsigned int)(l), -1);} while (0)
 #define CTR_OVERFLOWED(n) (!((n) & (1U<<31)))
 
+#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
 #define CTRL_READ(l,h,msrs,c) do {rdmsr(msrs->controls[(c)].addr, (l), (h));} while (0)
 #define CTRL_WRITE(l,h,msrs,c) do {wrmsr(msrs->controls[(c)].addr, (l), (h));} while (0)
 #define CTRL_SET_ACTIVE(n) (n |= (1<<22))
@@ -40,15 +42,21 @@ static unsigned long reset_value[NUM_COUNTERS];
  
 static void athlon_fill_in_addresses(struct op_msrs * const msrs)
 {
-       msrs->counters[0].addr = MSR_K7_PERFCTR0;
-       msrs->counters[1].addr = MSR_K7_PERFCTR1;
-       msrs->counters[2].addr = MSR_K7_PERFCTR2;
-       msrs->counters[3].addr = MSR_K7_PERFCTR3;
-
-       msrs->controls[0].addr = MSR_K7_EVNTSEL0;
-       msrs->controls[1].addr = MSR_K7_EVNTSEL1;
-       msrs->controls[2].addr = MSR_K7_EVNTSEL2;
-       msrs->controls[3].addr = MSR_K7_EVNTSEL3;
+       int i;
+
+       for (i=0; i < NUM_COUNTERS; i++) {
+               if (reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i))
+                       msrs->counters[i].addr = MSR_K7_PERFCTR0 + i;
+               else
+                       msrs->counters[i].addr = 0;
+       }
+
+       for (i=0; i < NUM_CONTROLS; i++) {
+               if (reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i))
+                       msrs->controls[i].addr = MSR_K7_EVNTSEL0 + i;
+               else
+                       msrs->controls[i].addr = 0;
+       }
 }
 
  
@@ -59,19 +67,23 @@ static void athlon_setup_ctrs(struct op_msrs const * const msrs)
  
        /* clear all counters */
        for (i = 0 ; i < NUM_CONTROLS; ++i) {
+               if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
+                       continue;
                CTRL_READ(low, high, msrs, i);
                CTRL_CLEAR(low);
                CTRL_WRITE(low, high, msrs, i);
        }
-       
+
        /* avoid a false detection of ctr overflows in NMI handler */
        for (i = 0; i < NUM_COUNTERS; ++i) {
+               if (unlikely(!CTR_IS_RESERVED(msrs,i)))
+                       continue;
                CTR_WRITE(1, msrs, i);
        }
 
        /* enable active counters */
        for (i = 0; i < NUM_COUNTERS; ++i) {
-               if (counter_config[i].enabled) {
+               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);
@@ -98,6 +110,8 @@ static int athlon_check_ctrs(struct pt_regs * const regs,
        int i;
 
        for (i = 0 ; i < NUM_COUNTERS; ++i) {
+               if (!reset_value[i])
+                       continue;
                CTR_READ(low, high, msrs, i);
                if (CTR_OVERFLOWED(low)) {
                        oprofile_add_sample(regs, i);
@@ -132,12 +146,27 @@ static void athlon_stop(struct op_msrs const * const msrs)
        /* Subtle: stop on all counters to avoid race with
         * setting our pm callback */
        for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+               if (!reset_value[i])
+                       continue;
                CTRL_READ(low, high, msrs, i);
                CTRL_SET_INACTIVE(low);
                CTRL_WRITE(low, high, msrs, i);
        }
 }
 
+static void athlon_shutdown(struct op_msrs const * const msrs)
+{
+       int i;
+
+       for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+               if (CTR_IS_RESERVED(msrs,i))
+                       release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
+       }
+       for (i = 0 ; i < NUM_CONTROLS ; ++i) {
+               if (CTRL_IS_RESERVED(msrs,i))
+                       release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
+       }
+}
 
 struct op_x86_model_spec const op_athlon_spec = {
        .num_counters = NUM_COUNTERS,
@@ -146,5 +175,6 @@ struct op_x86_model_spec const op_athlon_spec = {
        .setup_ctrs = &athlon_setup_ctrs,
        .check_ctrs = &athlon_check_ctrs,
        .start = &athlon_start,
-       .stop = &athlon_stop
+       .stop = &athlon_stop,
+       .shutdown = &athlon_shutdown
 };
index 7c61d357b82bc10302e1143068c1fca8a9a058dc..47925927b12f7cd7a7d293a021dc063d7462367c 100644 (file)
@@ -32,7 +32,7 @@
 #define NUM_CONTROLS_HT2 (NUM_ESCRS_HT2 + NUM_CCCRS_HT2)
 
 static unsigned int num_counters = NUM_COUNTERS_NON_HT;
-
+static unsigned int num_controls = NUM_CONTROLS_NON_HT;
 
 /* this has to be checked dynamically since the
    hyper-threadedness of a chip is discovered at
@@ -40,8 +40,10 @@ static unsigned int num_counters = NUM_COUNTERS_NON_HT;
 static inline void setup_num_counters(void)
 {
 #ifdef CONFIG_SMP
-       if (smp_num_siblings == 2)
+       if (smp_num_siblings == 2){
                num_counters = NUM_COUNTERS_HT2;
+               num_controls = NUM_CONTROLS_HT2;
+       }
 #endif
 }
 
@@ -97,15 +99,6 @@ static struct p4_counter_binding p4_counters [NUM_COUNTERS_NON_HT] = {
 
 #define NUM_UNUSED_CCCRS       NUM_CCCRS_NON_HT - NUM_COUNTERS_NON_HT
 
-/* All cccr we don't use. */
-static int p4_unused_cccr[NUM_UNUSED_CCCRS] = {
-       MSR_P4_BPU_CCCR1,       MSR_P4_BPU_CCCR3,
-       MSR_P4_MS_CCCR1,        MSR_P4_MS_CCCR3,
-       MSR_P4_FLAME_CCCR1,     MSR_P4_FLAME_CCCR3,
-       MSR_P4_IQ_CCCR0,        MSR_P4_IQ_CCCR1,
-       MSR_P4_IQ_CCCR2,        MSR_P4_IQ_CCCR3
-};
-
 /* p4 event codes in libop/op_event.h are indices into this table. */
 
 static struct p4_event_binding p4_events[NUM_EVENTS] = {
@@ -372,6 +365,8 @@ static struct p4_event_binding p4_events[NUM_EVENTS] = {
 #define CCCR_OVF_P(cccr) ((cccr) & (1U<<31))
 #define CCCR_CLEAR_OVF(cccr) ((cccr) &= (~(1U<<31)))
 
+#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
+#define CTR_IS_RESERVED(msrs,c) (msrs->counters[(c)].addr ? 1 : 0)
 #define CTR_READ(l,h,i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h));} while (0)
 #define CTR_WRITE(l,i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1);} while (0)
 #define CTR_OVERFLOW_P(ctr) (!((ctr) & 0x80000000))
@@ -401,29 +396,34 @@ static unsigned long reset_value[NUM_COUNTERS_NON_HT];
 static void p4_fill_in_addresses(struct op_msrs * const msrs)
 {
        unsigned int i; 
-       unsigned int addr, stag;
+       unsigned int addr, cccraddr, stag;
 
        setup_num_counters();
        stag = get_stagger();
 
-       /* the counter registers we pay attention to */
+       /* initialize some registers */
        for (i = 0; i < num_counters; ++i) {
-               msrs->counters[i].addr = 
-                       p4_counters[VIRT_CTR(stag, i)].counter_address;
+               msrs->counters[i].addr = 0;
        }
-
-       /* FIXME: bad feeling, we don't save the 10 counters we don't use. */
-
-       /* 18 CCCR registers */
-       for (i = 0, addr = MSR_P4_BPU_CCCR0 + stag;
-            addr <= MSR_P4_IQ_CCCR5; ++i, addr += addr_increment()) {
-               msrs->controls[i].addr = addr;
+       for (i = 0; i < num_controls; ++i) {
+               msrs->controls[i].addr = 0;
        }
        
+       /* the counter & cccr registers we pay attention to */
+       for (i = 0; i < num_counters; ++i) {
+               addr = p4_counters[VIRT_CTR(stag, i)].counter_address;
+               cccraddr = p4_counters[VIRT_CTR(stag, i)].cccr_address;
+               if (reserve_perfctr_nmi(addr)){
+                       msrs->counters[i].addr = addr;
+                       msrs->controls[i].addr = cccraddr;
+               }
+       }
+
        /* 43 ESCR registers in three or four discontiguous group */
        for (addr = MSR_P4_BSU_ESCR0 + stag;
             addr < MSR_P4_IQ_ESCR0; ++i, addr += addr_increment()) {
-               msrs->controls[i].addr = addr;
+               if (reserve_evntsel_nmi(addr))
+                       msrs->controls[i].addr = addr;
        }
 
        /* no IQ_ESCR0/1 on some models, we save a seconde time BSU_ESCR0/1
@@ -431,47 +431,57 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs)
        if (boot_cpu_data.x86_model >= 0x3) {
                for (addr = MSR_P4_BSU_ESCR0 + stag;
                     addr <= MSR_P4_BSU_ESCR1; ++i, addr += addr_increment()) {
-                       msrs->controls[i].addr = addr;
+                       if (reserve_evntsel_nmi(addr))
+                               msrs->controls[i].addr = addr;
                }
        } else {
                for (addr = MSR_P4_IQ_ESCR0 + stag;
                     addr <= MSR_P4_IQ_ESCR1; ++i, addr += addr_increment()) {
-                       msrs->controls[i].addr = addr;
+                       if (reserve_evntsel_nmi(addr))
+                               msrs->controls[i].addr = addr;
                }
        }
 
        for (addr = MSR_P4_RAT_ESCR0 + stag;
             addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
-               msrs->controls[i].addr = addr;
+               if (reserve_evntsel_nmi(addr))
+                       msrs->controls[i].addr = addr;
        }
        
        for (addr = MSR_P4_MS_ESCR0 + stag;
             addr <= MSR_P4_TC_ESCR1; ++i, addr += addr_increment()) { 
-               msrs->controls[i].addr = addr;
+               if (reserve_evntsel_nmi(addr))
+                       msrs->controls[i].addr = addr;
        }
        
        for (addr = MSR_P4_IX_ESCR0 + stag;
             addr <= MSR_P4_CRU_ESCR3; ++i, addr += addr_increment()) { 
-               msrs->controls[i].addr = addr;
+               if (reserve_evntsel_nmi(addr))
+                       msrs->controls[i].addr = addr;
        }
 
        /* there are 2 remaining non-contiguously located ESCRs */
 
        if (num_counters == NUM_COUNTERS_NON_HT) {              
                /* standard non-HT CPUs handle both remaining ESCRs*/
-               msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
-               msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
+               if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR5))
+                       msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
+               if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR4))
+                       msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
 
        } else if (stag == 0) {
                /* HT CPUs give the first remainder to the even thread, as
                   the 32nd control register */
-               msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
+               if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR4))
+                       msrs->controls[i++].addr = MSR_P4_CRU_ESCR4;
 
        } else {
                /* and two copies of the second to the odd thread,
                   for the 22st and 23nd control registers */
-               msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
-               msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
+               if (reserve_evntsel_nmi(MSR_P4_CRU_ESCR5)) {
+                       msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
+                       msrs->controls[i++].addr = MSR_P4_CRU_ESCR5;
+               }
        }
 }
 
@@ -544,7 +554,6 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs)
 {
        unsigned int i;
        unsigned int low, high;
-       unsigned int addr;
        unsigned int stag;
 
        stag = get_stagger();
@@ -557,59 +566,24 @@ static void p4_setup_ctrs(struct op_msrs const * const msrs)
 
        /* clear the cccrs we will use */
        for (i = 0 ; i < num_counters ; i++) {
+               if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
+                       continue;
                rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
                CCCR_CLEAR(low);
                CCCR_SET_REQUIRED_BITS(low);
                wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high);
        }
 
-       /* clear cccrs outside our concern */
-       for (i = stag ; i < NUM_UNUSED_CCCRS ; i += addr_increment()) {
-               rdmsr(p4_unused_cccr[i], low, high);
-               CCCR_CLEAR(low);
-               CCCR_SET_REQUIRED_BITS(low);
-               wrmsr(p4_unused_cccr[i], low, high);
-       }
-
        /* clear all escrs (including those outside our concern) */
-       for (addr = MSR_P4_BSU_ESCR0 + stag;
-            addr <  MSR_P4_IQ_ESCR0; addr += addr_increment()) {
-               wrmsr(addr, 0, 0);
-       }
-
-       /* On older models clear also MSR_P4_IQ_ESCR0/1 */
-       if (boot_cpu_data.x86_model < 0x3) {
-               wrmsr(MSR_P4_IQ_ESCR0, 0, 0);
-               wrmsr(MSR_P4_IQ_ESCR1, 0, 0);
-       }
-
-       for (addr = MSR_P4_RAT_ESCR0 + stag;
-            addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) {
-               wrmsr(addr, 0, 0);
-       }
-       
-       for (addr = MSR_P4_MS_ESCR0 + stag;
-            addr <= MSR_P4_TC_ESCR1; addr += addr_increment()){ 
-               wrmsr(addr, 0, 0);
-       }
-       
-       for (addr = MSR_P4_IX_ESCR0 + stag;
-            addr <= MSR_P4_CRU_ESCR3; addr += addr_increment()){ 
-               wrmsr(addr, 0, 0);
+       for (i = num_counters; i < num_controls; i++) {
+               if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
+                       continue;
+               wrmsr(msrs->controls[i].addr, 0, 0);
        }
 
-       if (num_counters == NUM_COUNTERS_NON_HT) {              
-               wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
-               wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
-       } else if (stag == 0) {
-               wrmsr(MSR_P4_CRU_ESCR4, 0, 0);
-       } else {
-               wrmsr(MSR_P4_CRU_ESCR5, 0, 0);
-       }               
-       
        /* setup all counters */
        for (i = 0 ; i < num_counters ; ++i) {
-               if (counter_config[i].enabled) {
+               if ((counter_config[i].enabled) && (CTRL_IS_RESERVED(msrs,i))) {
                        reset_value[i] = counter_config[i].count;
                        pmc_setup_one_p4_counter(i);
                        CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i));
@@ -696,12 +670,32 @@ static void p4_stop(struct op_msrs const * const msrs)
        stag = get_stagger();
 
        for (i = 0; i < num_counters; ++i) {
+               if (!reset_value[i])
+                       continue;
                CCCR_READ(low, high, VIRT_CTR(stag, i));
                CCCR_SET_DISABLE(low);
                CCCR_WRITE(low, high, VIRT_CTR(stag, i));
        }
 }
 
+static void p4_shutdown(struct op_msrs const * const msrs)
+{
+       int i;
+
+       for (i = 0 ; i < num_counters ; ++i) {
+               if (CTR_IS_RESERVED(msrs,i))
+                       release_perfctr_nmi(msrs->counters[i].addr);
+       }
+       /* some of the control registers are specially reserved in
+        * conjunction with the counter registers (hence the starting offset).
+        * This saves a few bits.
+        */
+       for (i = num_counters ; i < num_controls ; ++i) {
+               if (CTRL_IS_RESERVED(msrs,i))
+                       release_evntsel_nmi(msrs->controls[i].addr);
+       }
+}
+
 
 #ifdef CONFIG_SMP
 struct op_x86_model_spec const op_p4_ht2_spec = {
@@ -711,7 +705,8 @@ struct op_x86_model_spec const op_p4_ht2_spec = {
        .setup_ctrs = &p4_setup_ctrs,
        .check_ctrs = &p4_check_ctrs,
        .start = &p4_start,
-       .stop = &p4_stop
+       .stop = &p4_stop,
+       .shutdown = &p4_shutdown
 };
 #endif
 
@@ -722,5 +717,6 @@ struct op_x86_model_spec const op_p4_spec = {
        .setup_ctrs = &p4_setup_ctrs,
        .check_ctrs = &p4_check_ctrs,
        .start = &p4_start,
-       .stop = &p4_stop
+       .stop = &p4_stop,
+       .shutdown = &p4_shutdown
 };
index 5c3ab4b027ade11f9a32973c5e32df85af9abeeb..f88e05ba8eb34acd2aac784da0e9c592dcb20ef4 100644 (file)
 #define NUM_COUNTERS 2
 #define NUM_CONTROLS 2
 
+#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_OVERFLOWED(n) (!((n) & (1U<<31)))
 
+#define CTRL_IS_RESERVED(msrs,c) (msrs->controls[(c)].addr ? 1 : 0)
 #define CTRL_READ(l,h,msrs,c) do {rdmsr((msrs->controls[(c)].addr), (l), (h));} while (0)
 #define CTRL_WRITE(l,h,msrs,c) do {wrmsr((msrs->controls[(c)].addr), (l), (h));} while (0)
 #define CTRL_SET_ACTIVE(n) (n |= (1<<22))
@@ -41,11 +43,21 @@ static unsigned long reset_value[NUM_COUNTERS];
  
 static void ppro_fill_in_addresses(struct op_msrs * const msrs)
 {
-       msrs->counters[0].addr = MSR_P6_PERFCTR0;
-       msrs->counters[1].addr = MSR_P6_PERFCTR1;
+       int i;
+
+       for (i=0; i < NUM_COUNTERS; i++) {
+               if (reserve_perfctr_nmi(MSR_P6_PERFCTR0 + i))
+                       msrs->counters[i].addr = MSR_P6_PERFCTR0 + i;
+               else
+                       msrs->counters[i].addr = 0;
+       }
        
-       msrs->controls[0].addr = MSR_P6_EVNTSEL0;
-       msrs->controls[1].addr = MSR_P6_EVNTSEL1;
+       for (i=0; i < NUM_CONTROLS; i++) {
+               if (reserve_evntsel_nmi(MSR_P6_EVNTSEL0 + i))
+                       msrs->controls[i].addr = MSR_P6_EVNTSEL0 + i;
+               else
+                       msrs->controls[i].addr = 0;
+       }
 }
 
 
@@ -56,6 +68,8 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
 
        /* clear all counters */
        for (i = 0 ; i < NUM_CONTROLS; ++i) {
+               if (unlikely(!CTRL_IS_RESERVED(msrs,i)))
+                       continue;
                CTRL_READ(low, high, msrs, i);
                CTRL_CLEAR(low);
                CTRL_WRITE(low, high, msrs, i);
@@ -63,12 +77,14 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
        
        /* avoid a false detection of ctr overflows in NMI handler */
        for (i = 0; i < NUM_COUNTERS; ++i) {
+               if (unlikely(!CTR_IS_RESERVED(msrs,i)))
+                       continue;
                CTR_WRITE(1, msrs, i);
        }
 
        /* enable active counters */
        for (i = 0; i < NUM_COUNTERS; ++i) {
-               if (counter_config[i].enabled) {
+               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);
@@ -81,6 +97,8 @@ static void ppro_setup_ctrs(struct op_msrs const * const msrs)
                        CTRL_SET_UM(low, counter_config[i].unit_mask);
                        CTRL_SET_EVENT(low, counter_config[i].event);
                        CTRL_WRITE(low, high, msrs, i);
+               } else {
+                       reset_value[i] = 0;
                }
        }
 }
@@ -93,6 +111,8 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
        int i;
  
        for (i = 0 ; i < NUM_COUNTERS; ++i) {
+               if (!reset_value[i])
+                       continue;
                CTR_READ(low, high, msrs, i);
                if (CTR_OVERFLOWED(low)) {
                        oprofile_add_sample(regs, i);
@@ -118,18 +138,38 @@ static int ppro_check_ctrs(struct pt_regs * const regs,
 static void ppro_start(struct op_msrs const * const msrs)
 {
        unsigned int low,high;
-       CTRL_READ(low, high, msrs, 0);
-       CTRL_SET_ACTIVE(low);
-       CTRL_WRITE(low, high, msrs, 0);
+
+       if (reset_value[0]) {
+               CTRL_READ(low, high, msrs, 0);
+               CTRL_SET_ACTIVE(low);
+               CTRL_WRITE(low, high, msrs, 0);
+       }
 }
 
 
 static void ppro_stop(struct op_msrs const * const msrs)
 {
        unsigned int low,high;
-       CTRL_READ(low, high, msrs, 0);
-       CTRL_SET_INACTIVE(low);
-       CTRL_WRITE(low, high, msrs, 0);
+
+       if (reset_value[0]) {
+               CTRL_READ(low, high, msrs, 0);
+               CTRL_SET_INACTIVE(low);
+               CTRL_WRITE(low, high, msrs, 0);
+       }
+}
+
+static void ppro_shutdown(struct op_msrs const * const msrs)
+{
+       int i;
+
+       for (i = 0 ; i < NUM_COUNTERS ; ++i) {
+               if (CTR_IS_RESERVED(msrs,i))
+                       release_perfctr_nmi(MSR_P6_PERFCTR0 + i);
+       }
+       for (i = 0 ; i < NUM_CONTROLS ; ++i) {
+               if (CTRL_IS_RESERVED(msrs,i))
+                       release_evntsel_nmi(MSR_P6_EVNTSEL0 + i);
+       }
 }
 
 
@@ -140,5 +180,6 @@ struct op_x86_model_spec const op_ppro_spec = {
        .setup_ctrs = &ppro_setup_ctrs,
        .check_ctrs = &ppro_check_ctrs,
        .start = &ppro_start,
-       .stop = &ppro_stop
+       .stop = &ppro_stop,
+       .shutdown = &ppro_shutdown
 };
index 123b7e90a9eed803699470e6eb44010f8f2428db..abb1aa95b979f8dbc0fa65a90210d11409715f61 100644 (file)
@@ -40,6 +40,7 @@ struct op_x86_model_spec {
                struct op_msrs const * const msrs);
        void (*start)(struct op_msrs const * const msrs);
        void (*stop)(struct op_msrs const * const msrs);
+       void (*shutdown)(struct op_msrs const * const msrs);
 };
 
 extern struct op_x86_model_spec const op_ppro_spec;
index 62ad75c57e6ae41047a40d480814fabdfdb28b5a..1594d2f55c8f13e5fc4b22389456957d8bacefb1 100644 (file)
@@ -11,4 +11,4 @@ pci-y                         += legacy.o irq.o
 pci-$(CONFIG_X86_VISWS)                := visws.o fixup.o
 pci-$(CONFIG_X86_NUMAQ)                := numa.o irq.o
 
-obj-y                          += $(pci-y) common.o
+obj-y                          += $(pci-y) common.o early.o
index 0a362e3aeac55aba443e5901a71bbe7e465e841a..68bce194e688a1903480425b3db8dc37802127f0 100644 (file)
@@ -242,6 +242,10 @@ char * __devinit  pcibios_setup(char *str)
                acpi_noirq_set();
                return NULL;
        }
+       else if (!strcmp(str, "noearly")) {
+               pci_probe |= PCI_PROBE_NOEARLY;
+               return NULL;
+       }
 #ifndef CONFIG_X86_VISWS
        else if (!strcmp(str, "usepirqmask")) {
                pci_probe |= PCI_USE_PIRQ_MASK;
index 5d81fb51037551b9ede92c2f0f7f785a2a6e4e2e..5acf0b4743cfc74ba1cc04e34e708449a3d03ecc 100644 (file)
@@ -254,7 +254,16 @@ static int __init pci_check_type2(void)
        return works;
 }
 
-void __init pci_direct_init(void)
+void __init pci_direct_init(int type)
+{
+       printk(KERN_INFO "PCI: Using configuration type %d\n", type);
+       if (type == 1)
+               raw_pci_ops = &pci_direct_conf1;
+       else
+               raw_pci_ops = &pci_direct_conf2;
+}
+
+int __init pci_direct_probe(void)
 {
        struct resource *region, *region2;
 
@@ -264,19 +273,16 @@ void __init pci_direct_init(void)
        if (!region)
                goto type2;
 
-       if (pci_check_type1()) {
-               printk(KERN_INFO "PCI: Using configuration type 1\n");
-               raw_pci_ops = &pci_direct_conf1;
-               return;
-       }
+       if (pci_check_type1())
+               return 1;
        release_resource(region);
 
  type2:
        if ((pci_probe & PCI_PROBE_CONF2) == 0)
-               return;
+               return 0;
        region = request_region(0xCF8, 4, "PCI conf2");
        if (!region)
-               return;
+               return 0;
        region2 = request_region(0xC000, 0x1000, "PCI conf2");
        if (!region2)
                goto fail2;
@@ -284,10 +290,11 @@ void __init pci_direct_init(void)
        if (pci_check_type2()) {
                printk(KERN_INFO "PCI: Using configuration type 2\n");
                raw_pci_ops = &pci_direct_conf2;
-               return;
+               return 2;
        }
 
        release_resource(region2);
  fail2:
        release_resource(region);
+       return 0;
 }
diff --git a/arch/i386/pci/early.c b/arch/i386/pci/early.c
new file mode 100644 (file)
index 0000000..713d6c8
--- /dev/null
@@ -0,0 +1,52 @@
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <asm/pci-direct.h>
+#include <asm/io.h>
+#include "pci.h"
+
+/* Direct PCI access. This is used for PCI accesses in early boot before
+   the PCI subsystem works. */
+
+#define PDprintk(x...)
+
+u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset)
+{
+       u32 v;
+       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+       v = inl(0xcfc);
+       if (v != 0xffffffff)
+               PDprintk("%x reading 4 from %x: %x\n", slot, offset, v);
+       return v;
+}
+
+u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset)
+{
+       u8 v;
+       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+       v = inb(0xcfc + (offset&3));
+       PDprintk("%x reading 1 from %x: %x\n", slot, offset, v);
+       return v;
+}
+
+u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset)
+{
+       u16 v;
+       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+       v = inw(0xcfc + (offset&2));
+       PDprintk("%x reading 2 from %x: %x\n", slot, offset, v);
+       return v;
+}
+
+void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
+                                   u32 val)
+{
+       PDprintk("%x writing to %x: %x\n", slot, offset, val);
+       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
+       outl(val, 0xcfc);
+}
+
+int early_pci_allowed(void)
+{
+       return (pci_probe & (PCI_PROBE_CONF1|PCI_PROBE_NOEARLY)) ==
+                       PCI_PROBE_CONF1;
+}
index 51087a9d91720153178dcdc876357101d2387cb8..d028e1b05c3697e56e64631b0863cb3d90819fd3 100644 (file)
@@ -6,8 +6,13 @@
    in the right sequence from here. */
 static __init int pci_access_init(void)
 {
+       int type = 0;
+
+#ifdef CONFIG_PCI_DIRECT
+       type = pci_direct_probe();
+#endif
 #ifdef CONFIG_PCI_MMCONFIG
-       pci_mmcfg_init();
+       pci_mmcfg_init(type);
 #endif
        if (raw_pci_ops)
                return 0;
@@ -21,7 +26,7 @@ static __init int pci_access_init(void)
         * fails.
         */
 #ifdef CONFIG_PCI_DIRECT
-       pci_direct_init();
+       pci_direct_init(type);
 #endif
        return 0;
 }
index 972180f738d9ae0d15fe059953fe2985cf454c09..05be8db58a8cee783bde63b5f207d7e8137fd7fc 100644 (file)
@@ -151,6 +151,38 @@ static struct pci_raw_ops pci_mmcfg = {
        .write =        pci_mmcfg_write,
 };
 
+
+static __init void 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++) {
+               num_buses = pci_mmcfg_config[i].end_bus_number -
+                   pci_mmcfg_config[i].start_bus_number + 1;
+               res->name = names;
+               snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
+                       pci_mmcfg_config[i].pci_segment_group_number);
+               res->start = pci_mmcfg_config[i].base_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;
+       }
+}
+
 /* 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
@@ -187,7 +219,9 @@ static __init void unreachable_devices(void)
        }
 }
 
-void __init pci_mmcfg_init(void)
+
+
+void __init pci_mmcfg_init(int type)
 {
        if ((pci_probe & PCI_PROBE_MMCONF) == 0)
                return;
@@ -198,7 +232,9 @@ void __init pci_mmcfg_init(void)
            (pci_mmcfg_config[0].base_address == 0))
                return;
 
-       if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+       /* 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].base_address,
                        pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
                        E820_RESERVED)) {
                printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
@@ -212,4 +248,5 @@ void __init pci_mmcfg_init(void)
        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
 
        unreachable_devices();
+       pci_mmcfg_insert_resources();
 }
index bf4e79335388b533b6149dcf403533b6ce687c7e..1814f74569c63efd415bdfa4393a9471107a3742 100644 (file)
@@ -17,6 +17,7 @@
 #define PCI_PROBE_CONF2                0x0004
 #define PCI_PROBE_MMCONF       0x0008
 #define PCI_PROBE_MASK         0x000f
+#define PCI_PROBE_NOEARLY      0x0010
 
 #define PCI_NO_SORT            0x0100
 #define PCI_BIOS_SORT          0x0200
@@ -81,7 +82,9 @@ extern int pci_conf1_write(unsigned int seg, unsigned int bus,
 extern int pci_conf1_read(unsigned int seg, unsigned int bus,
                          unsigned int devfn, int reg, int len, u32 *value);
 
-extern void pci_direct_init(void);
+extern int pci_direct_probe(void);
+extern void pci_direct_init(int type);
 extern void pci_pcbios_init(void);
-extern void pci_mmcfg_init(void);
+extern void pci_mmcfg_init(int type);
 extern void pcibios_sort(void);
+
index f521f2f60a7802b65b20289effe6d40d1801439e..0b7f701d5cf7e38253465e82c1261c92dc854a15 100644 (file)
@@ -356,6 +356,9 @@ config NODES_SHIFT
          MAX_NUMNODES will be 2^(This value).
          If in doubt, use the default.
 
+config ARCH_POPULATES_NODE_MAP
+       def_bool y
+
 # VIRTUAL_MEM_MAP and FLAT_NODE_MEM_MAP are functionally equivalent.
 # VIRTUAL_MEM_MAP has been retained for historical reasons.
 config VIRTUAL_MEM_MAP
@@ -420,6 +423,14 @@ config IA64_PALINFO
 config SGI_SN
        def_bool y if (IA64_SGI_SN2 || IA64_GENERIC)
 
+config IA64_ESI
+       bool "ESI (Extensible SAL Interface) support"
+       help
+         If you say Y here, support is built into the kernel to
+         make ESI calls.  ESI calls are used to support vendor-specific
+         firmware extensions, such as the ability to inject memory-errors
+         for test-purposes.  If you're unsure, say N.
+
 source "drivers/sn/Kconfig"
 
 source "drivers/firmware/Kconfig"
index 6aa3c51619ca77bcb1b88410a21c43e7184aea8a..bddbd22706ed1ad76a791635b621784a80cde5a9 100644 (file)
@@ -1942,7 +1942,7 @@ struct sysctl32 {
        unsigned int    __unused[4];
 };
 
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
 asmlinkage long
 sys32_sysctl (struct sysctl32 __user *args)
 {
index ad8215a3c586948f3cf92c2e6c80f31a5ff36aa5..31497496eb4bf2d2353b99970f84688ec8959a73 100644 (file)
@@ -32,6 +32,11 @@ obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR)        += uncached.o
 obj-$(CONFIG_AUDIT)            += audit.o
 mca_recovery-y                 += mca_drv.o mca_drv_asm.o
 
+obj-$(CONFIG_IA64_ESI)         += esi.o
+ifneq ($(CONFIG_IA64_ESI),)
+obj-y                          += esi_stub.o   # must be in kernel proper
+endif
+
 # The gate DSO image is built using a special linker script.
 targets += gate.so gate-syms.o
 
index fef06571be99c9a4edc27caaf04f61e715a3eeef..12701cf32d9944de96a3fa609788d50fc79b8518 100644 (file)
@@ -1605,8 +1605,8 @@ sys_call_table:
        data8 sys_ni_syscall                    // 1295 reserved for ppoll
        data8 sys_unshare
        data8 sys_splice
-       data8 sys_ni_syscall                    // reserved for set_robust_list
-       data8 sys_ni_syscall                    // reserved for get_robust_list
+       data8 sys_set_robust_list
+       data8 sys_get_robust_list
        data8 sys_sync_file_range               // 1300
        data8 sys_tee
        data8 sys_vmsplice
diff --git a/arch/ia64/kernel/esi.c b/arch/ia64/kernel/esi.c
new file mode 100644 (file)
index 0000000..ebf4e98
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Extensible SAL Interface (ESI) support routines.
+ *
+ * Copyright (C) 2006 Hewlett-Packard Co
+ *     Alex Williamson <alex.williamson@hp.com>
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include <asm/esi.h>
+#include <asm/sal.h>
+
+MODULE_AUTHOR("Alex Williamson <alex.williamson@hp.com>");
+MODULE_DESCRIPTION("Extensible SAL Interface (ESI) support");
+MODULE_LICENSE("GPL");
+
+#define MODULE_NAME    "esi"
+
+#define ESI_TABLE_GUID                                 \
+    EFI_GUID(0x43EA58DC, 0xCF28, 0x4b06, 0xB3,         \
+            0x91, 0xB7, 0x50, 0x59, 0x34, 0x2B, 0xD4)
+
+enum esi_systab_entry_type {
+       ESI_DESC_ENTRY_POINT = 0
+};
+
+/*
+ * Entry type: Size:
+ *     0       48
+ */
+#define ESI_DESC_SIZE(type)    "\060"[(unsigned) (type)]
+
+typedef struct ia64_esi_desc_entry_point {
+       u8 type;
+       u8 reserved1[15];
+       u64 esi_proc;
+       u64 gp;
+       efi_guid_t guid;
+} ia64_esi_desc_entry_point_t;
+
+struct pdesc {
+       void *addr;
+       void *gp;
+};
+
+static struct ia64_sal_systab *esi_systab;
+
+static int __init esi_init (void)
+{
+       efi_config_table_t *config_tables;
+       struct ia64_sal_systab *systab;
+       unsigned long esi = 0;
+       char *p;
+       int i;
+
+       config_tables = __va(efi.systab->tables);
+
+       for (i = 0; i < (int) efi.systab->nr_tables; ++i) {
+               if (efi_guidcmp(config_tables[i].guid, ESI_TABLE_GUID) == 0) {
+                       esi = config_tables[i].table;
+                       break;
+               }
+       }
+
+       if (!esi)
+               return -ENODEV;;
+
+       systab = __va(esi);
+
+       if (strncmp(systab->signature, "ESIT", 4) != 0) {
+               printk(KERN_ERR "bad signature in ESI system table!");
+               return -ENODEV;
+       }
+
+       p = (char *) (systab + 1);
+       for (i = 0; i < systab->entry_count; i++) {
+               /*
+                * The first byte of each entry type contains the type
+                * descriptor.
+                */
+               switch (*p) {
+                     case ESI_DESC_ENTRY_POINT:
+                       break;
+                     default:
+                       printk(KERN_WARNING "Unkown table type %d found in "
+                              "ESI table, ignoring rest of table\n", *p);
+                       return -ENODEV;
+               }
+
+               p += ESI_DESC_SIZE(*p);
+       }
+
+       esi_systab = systab;
+       return 0;
+}
+
+
+int ia64_esi_call (efi_guid_t guid, struct ia64_sal_retval *isrvp,
+                  enum esi_proc_type proc_type, u64 func,
+                  u64 arg1, u64 arg2, u64 arg3, u64 arg4, u64 arg5, u64 arg6,
+                  u64 arg7)
+{
+       struct ia64_fpreg fr[6];
+       unsigned long flags = 0;
+       int i;
+       char *p;
+
+       if (!esi_systab)
+               return -1;
+
+       p = (char *) (esi_systab + 1);
+       for (i = 0; i < esi_systab->entry_count; i++) {
+               if (*p == ESI_DESC_ENTRY_POINT) {
+                       ia64_esi_desc_entry_point_t *esi = (void *)p;
+                       if (!efi_guidcmp(guid, esi->guid)) {
+                               ia64_sal_handler esi_proc;
+                               struct pdesc pdesc;
+
+                               pdesc.addr = __va(esi->esi_proc);
+                               pdesc.gp = __va(esi->gp);
+
+                               esi_proc = (ia64_sal_handler) &pdesc;
+
+                               ia64_save_scratch_fpregs(fr);
+                               if (proc_type == ESI_PROC_SERIALIZED)
+                                       spin_lock_irqsave(&sal_lock, flags);
+                               else if (proc_type == ESI_PROC_MP_SAFE)
+                                       local_irq_save(flags);
+                               else
+                                       preempt_disable();
+                               *isrvp = (*esi_proc)(func, arg1, arg2, arg3,
+                                                    arg4, arg5, arg6, arg7);
+                               if (proc_type == ESI_PROC_SERIALIZED)
+                                       spin_unlock_irqrestore(&sal_lock,
+                                                              flags);
+                               else if (proc_type == ESI_PROC_MP_SAFE)
+                                       local_irq_restore(flags);
+                               else
+                                       preempt_enable();
+                               ia64_load_scratch_fpregs(fr);
+                               return 0;
+                       }
+               }
+               p += ESI_DESC_SIZE(*p);
+       }
+       return -1;
+}
+EXPORT_SYMBOL_GPL(ia64_esi_call);
+
+int ia64_esi_call_phys (efi_guid_t guid, struct ia64_sal_retval *isrvp,
+                       u64 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4,
+                       u64 arg5, u64 arg6, u64 arg7)
+{
+       struct ia64_fpreg fr[6];
+       unsigned long flags;
+       u64 esi_params[8];
+       char *p;
+       int i;
+
+       if (!esi_systab)
+               return -1;
+
+       p = (char *) (esi_systab + 1);
+       for (i = 0; i < esi_systab->entry_count; i++) {
+               if (*p == ESI_DESC_ENTRY_POINT) {
+                       ia64_esi_desc_entry_point_t *esi = (void *)p;
+                       if (!efi_guidcmp(guid, esi->guid)) {
+                               ia64_sal_handler esi_proc;
+                               struct pdesc pdesc;
+
+                               pdesc.addr = (void *)esi->esi_proc;
+                               pdesc.gp = (void *)esi->gp;
+
+                               esi_proc = (ia64_sal_handler) &pdesc;
+
+                               esi_params[0] = func;
+                               esi_params[1] = arg1;
+                               esi_params[2] = arg2;
+                               esi_params[3] = arg3;
+                               esi_params[4] = arg4;
+                               esi_params[5] = arg5;
+                               esi_params[6] = arg6;
+                               esi_params[7] = arg7;
+                               ia64_save_scratch_fpregs(fr);
+                               spin_lock_irqsave(&sal_lock, flags);
+                               *isrvp = esi_call_phys(esi_proc, esi_params);
+                               spin_unlock_irqrestore(&sal_lock, flags);
+                               ia64_load_scratch_fpregs(fr);
+                               return 0;
+                       }
+               }
+               p += ESI_DESC_SIZE(*p);
+       }
+       return -1;
+}
+EXPORT_SYMBOL_GPL(ia64_esi_call_phys);
+
+static void __exit esi_exit (void)
+{
+}
+
+module_init(esi_init);
+module_exit(esi_exit); /* makes module removable... */
diff --git a/arch/ia64/kernel/esi_stub.S b/arch/ia64/kernel/esi_stub.S
new file mode 100644 (file)
index 0000000..6b3d6c1
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * ESI call stub.
+ *
+ * Copyright (C) 2005 Hewlett-Packard Co
+ *     Alex Williamson <alex.williamson@hp.com>
+ *
+ * Based on EFI call stub by David Mosberger.  The stub is virtually
+ * identical to the one for EFI phys-mode calls, except that ESI
+ * calls may have up to 8 arguments, so they get passed to this routine
+ * through memory.
+ *
+ * This stub allows us to make ESI calls in physical mode with interrupts
+ * turned off.  ESI calls may not support calling from virtual mode.
+ *
+ * Google for "Extensible SAL specification" for a document describing the
+ * ESI standard.
+ */
+
+/*
+ * PSR settings as per SAL spec (Chapter 8 in the "IA-64 System
+ * Abstraction Layer Specification", revision 2.6e).  Note that
+ * psr.dfl and psr.dfh MUST be cleared, despite what this manual says.
+ * Otherwise, SAL dies whenever it's trying to do an IA-32 BIOS call
+ * (the br.ia instruction fails unless psr.dfl and psr.dfh are
+ * cleared).  Fortunately, SAL promises not to touch the floating
+ * point regs, so at least we don't have to save f2-f127.
+ */
+#define PSR_BITS_TO_CLEAR                                              \
+       (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT | IA64_PSR_RT |         \
+        IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED |        \
+        IA64_PSR_DFL | IA64_PSR_DFH)
+
+#define PSR_BITS_TO_SET                                                        \
+       (IA64_PSR_BN)
+
+#include <asm/processor.h>
+#include <asm/asmmacro.h>
+
+/*
+ * Inputs:
+ *     in0 = address of function descriptor of ESI routine to call
+ *     in1 = address of array of ESI parameters
+ *
+ * Outputs:
+ *     r8 = result returned by called function
+ */
+GLOBAL_ENTRY(esi_call_phys)
+       .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)
+       alloc loc1=ar.pfs,2,7,8,0
+       ld8 r2=[in0],8                  // load ESI function's entry point
+       mov loc0=rp
+       .body
+       ;;
+       ld8 out0=[in1],8                // ESI params loaded from array
+       ;;                              // passing all as inputs doesn't work
+       ld8 out1=[in1],8
+       ;;
+       ld8 out2=[in1],8
+       ;;
+       ld8 out3=[in1],8
+       ;;
+       ld8 out4=[in1],8
+       ;;
+       ld8 out5=[in1],8
+       ;;
+       ld8 out6=[in1],8
+       ;;
+       ld8 out7=[in1]
+       mov loc2=gp                     // save global pointer
+       mov loc4=ar.rsc                 // save RSE configuration
+       mov ar.rsc=0                    // put RSE in enforced lazy, LE mode
+       ;;
+       ld8 gp=[in0]                    // load ESI function's global pointer
+       movl r16=PSR_BITS_TO_CLEAR
+       mov loc3=psr                    // save processor status word
+       movl r17=PSR_BITS_TO_SET
+       ;;
+       or loc3=loc3,r17
+       mov b6=r2
+       ;;
+       andcm r16=loc3,r16      // get psr with IT, DT, and RT bits cleared
+       br.call.sptk.many rp=ia64_switch_mode_phys
+.ret0: mov loc5=r19                    // old ar.bsp
+       mov loc6=r20                    // old sp
+       br.call.sptk.many rp=b6         // call the ESI function
+.ret1: mov ar.rsc=0                    // put RSE in enforced lazy, LE mode
+       mov r16=loc3                    // save virtual mode psr
+       mov r19=loc5                    // save virtual mode bspstore
+       mov r20=loc6                    // save virtual mode sp
+       br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
+.ret2: mov ar.rsc=loc4                 // restore RSE configuration
+       mov ar.pfs=loc1
+       mov rp=loc0
+       mov gp=loc2
+       br.ret.sptk.many rp
+END(esi_call_phys)
index 3ead20fb6f4b2f45d7ec6f6bee19f82a3d4364af..879c1817bd1c8589c1ff7c85a659e777b67abc50 100644 (file)
@@ -105,5 +105,9 @@ EXPORT_SYMBOL(ia64_spinlock_contention);
 # endif
 #endif
 
+#if defined(CONFIG_IA64_ESI) || defined(CONFIG_IA64_ESI_MODULE)
+extern void esi_call_phys (void);
+EXPORT_SYMBOL_GPL(esi_call_phys);
+#endif
 extern char ia64_ivt[];
 EXPORT_SYMBOL(ia64_ivt);
index 781960f80b6f12c2d7c8be375157086c3b16a72d..169ec3a7156ce4dc349769e90ead997bed4f4329 100644 (file)
@@ -136,10 +136,8 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint  slot,
 static int __kprobes unsupported_inst(uint template, uint  slot,
                                      uint major_opcode,
                                      unsigned long kprobe_inst,
-                                     struct kprobe *p)
+                                     unsigned long addr)
 {
-       unsigned long addr = (unsigned long)p->addr;
-
        if (bundle_encoding[template][slot] == I) {
                switch (major_opcode) {
                        case 0x0: //I_UNIT_MISC_OPCODE:
@@ -217,7 +215,7 @@ static void __kprobes prepare_break_inst(uint template, uint  slot,
                                         struct kprobe *p)
 {
        unsigned long break_inst = BREAK_INST;
-       bundle_t *bundle = &p->ainsn.insn.bundle;
+       bundle_t *bundle = &p->opcode.bundle;
 
        /*
         * Copy the original kprobe_inst qualifying predicate(qp)
@@ -423,11 +421,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
        unsigned long kprobe_inst=0;
        unsigned int slot = addr & 0xf, template, major_opcode = 0;
-       bundle_t *bundle = &p->ainsn.insn.bundle;
-
-       memcpy(&p->opcode.bundle, kprobe_addr, sizeof(bundle_t));
-       memcpy(&p->ainsn.insn.bundle, kprobe_addr, sizeof(bundle_t));
+       bundle_t *bundle;
 
+       bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle;
        template = bundle->quad0.template;
 
        if(valid_kprobe_addr(template, slot, addr))
@@ -440,20 +436,19 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        /* Get kprobe_inst and major_opcode from the bundle */
        get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
 
-       if (unsupported_inst(template, slot, major_opcode, kprobe_inst, p))
+       if (unsupported_inst(template, slot, major_opcode, kprobe_inst, addr))
                        return -EINVAL;
 
-       prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
 
-       return 0;
-}
+       p->ainsn.insn = get_insn_slot();
+       if (!p->ainsn.insn)
+               return -ENOMEM;
+       memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t));
+       memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t));
 
-void __kprobes flush_insn_slot(struct kprobe *p)
-{
-       unsigned long arm_addr;
+       prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
 
-       arm_addr = ((unsigned long)&p->opcode.bundle) & ~0xFULL;
-       flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+       return 0;
 }
 
 void __kprobes arch_arm_kprobe(struct kprobe *p)
@@ -461,9 +456,10 @@ void __kprobes arch_arm_kprobe(struct kprobe *p)
        unsigned long addr = (unsigned long)p->addr;
        unsigned long arm_addr = addr & ~0xFULL;
 
-       flush_insn_slot(p);
-       memcpy((char *)arm_addr, &p->ainsn.insn.bundle, sizeof(bundle_t));
-       flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+       flush_icache_range((unsigned long)p->ainsn.insn,
+                       (unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
+       memcpy((char *)arm_addr, &p->opcode, sizeof(kprobe_opcode_t));
+       flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
 }
 
 void __kprobes arch_disarm_kprobe(struct kprobe *p)
@@ -471,11 +467,18 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
        unsigned long addr = (unsigned long)p->addr;
        unsigned long arm_addr = addr & ~0xFULL;
 
-       /* p->opcode contains the original unaltered bundle */
-       memcpy((char *) arm_addr, (char *) &p->opcode.bundle, sizeof(bundle_t));
-       flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+       /* p->ainsn.insn contains the original unaltered kprobe_opcode_t */
+       memcpy((char *) arm_addr, (char *) p->ainsn.insn,
+                                        sizeof(kprobe_opcode_t));
+       flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
 }
 
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+       mutex_lock(&kprobe_mutex);
+       free_insn_slot(p->ainsn.insn);
+       mutex_unlock(&kprobe_mutex);
+}
 /*
  * We are resuming execution after a single step fault, so the pt_regs
  * structure reflects the register state after we executed the instruction
@@ -486,12 +489,12 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
  */
 static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
 {
-       unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL;
+       unsigned long bundle_addr = (unsigned long) (&p->ainsn.insn->bundle);
        unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
        unsigned long template;
        int slot = ((unsigned long)p->addr & 0xf);
 
-       template = p->opcode.bundle.quad0.template;
+       template = p->ainsn.insn->bundle.quad0.template;
 
        if (slot == 1 && bundle_encoding[template][1] == L)
                slot = 2;
@@ -553,7 +556,7 @@ turn_ss_off:
 
 static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
 {
-       unsigned long bundle_addr = (unsigned long) &p->opcode.bundle;
+       unsigned long bundle_addr = (unsigned long) &p->ainsn.insn->bundle;
        unsigned long slot = (unsigned long)p->addr & 0xf;
 
        /* single step inline if break instruction */
@@ -768,6 +771,12 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
                 */
                if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
                        return 1;
+               /*
+                * In case the user-specified fault handler returned
+                * zero, try to fix up.
+                */
+               if (ia64_done_with_exception(regs))
+                       return 1;
 
                /*
                 * Let ia64_do_page_fault() fix it.
index 2fbe4536fe181b5574d99a77add70e5330a5f490..bfbd8986153b96101d00ba27b1ccbb2ac8d25f17 100644 (file)
@@ -54,6 +54,9 @@
  *
  * 2005-10-07 Keith Owens <kaos@sgi.com>
  *           Add notify_die() hooks.
+ *
+ * 2006-09-15 Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
+ *           Add printing support for MCA/INIT.
  */
 #include <linux/types.h>
 #include <linux/init.h>
@@ -136,11 +139,175 @@ extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe);
 
 static int mca_init __initdata;
 
+/*
+ * limited & delayed printing support for MCA/INIT handler
+ */
+
+#define mprintk(fmt...) ia64_mca_printk(fmt)
+
+#define MLOGBUF_SIZE (512+256*NR_CPUS)
+#define MLOGBUF_MSGMAX 256
+static char mlogbuf[MLOGBUF_SIZE];
+static DEFINE_SPINLOCK(mlogbuf_wlock); /* mca context only */
+static DEFINE_SPINLOCK(mlogbuf_rlock); /* normal context only */
+static unsigned long mlogbuf_start;
+static unsigned long mlogbuf_end;
+static unsigned int mlogbuf_finished = 0;
+static unsigned long mlogbuf_timestamp = 0;
+
+static int loglevel_save = -1;
+#define BREAK_LOGLEVEL(__console_loglevel)             \
+       oops_in_progress = 1;                           \
+       if (loglevel_save < 0)                          \
+               loglevel_save = __console_loglevel;     \
+       __console_loglevel = 15;
+
+#define RESTORE_LOGLEVEL(__console_loglevel)           \
+       if (loglevel_save >= 0) {                       \
+               __console_loglevel = loglevel_save;     \
+               loglevel_save = -1;                     \
+       }                                               \
+       mlogbuf_finished = 0;                           \
+       oops_in_progress = 0;
+
+/*
+ * Push messages into buffer, print them later if not urgent.
+ */
+void ia64_mca_printk(const char *fmt, ...)
+{
+       va_list args;
+       int printed_len;
+       char temp_buf[MLOGBUF_MSGMAX];
+       char *p;
+
+       va_start(args, fmt);
+       printed_len = vscnprintf(temp_buf, sizeof(temp_buf), fmt, args);
+       va_end(args);
+
+       /* Copy the output into mlogbuf */
+       if (oops_in_progress) {
+               /* mlogbuf was abandoned, use printk directly instead. */
+               printk(temp_buf);
+       } else {
+               spin_lock(&mlogbuf_wlock);
+               for (p = temp_buf; *p; p++) {
+                       unsigned long next = (mlogbuf_end + 1) % MLOGBUF_SIZE;
+                       if (next != mlogbuf_start) {
+                               mlogbuf[mlogbuf_end] = *p;
+                               mlogbuf_end = next;
+                       } else {
+                               /* buffer full */
+                               break;
+                       }
+               }
+               mlogbuf[mlogbuf_end] = '\0';
+               spin_unlock(&mlogbuf_wlock);
+       }
+}
+EXPORT_SYMBOL(ia64_mca_printk);
+
+/*
+ * Print buffered messages.
+ *  NOTE: call this after returning normal context. (ex. from salinfod)
+ */
+void ia64_mlogbuf_dump(void)
+{
+       char temp_buf[MLOGBUF_MSGMAX];
+       char *p;
+       unsigned long index;
+       unsigned long flags;
+       unsigned int printed_len;
+
+       /* Get output from mlogbuf */
+       while (mlogbuf_start != mlogbuf_end) {
+               temp_buf[0] = '\0';
+               p = temp_buf;
+               printed_len = 0;
+
+               spin_lock_irqsave(&mlogbuf_rlock, flags);
+
+               index = mlogbuf_start;
+               while (index != mlogbuf_end) {
+                       *p = mlogbuf[index];
+                       index = (index + 1) % MLOGBUF_SIZE;
+                       if (!*p)
+                               break;
+                       p++;
+                       if (++printed_len >= MLOGBUF_MSGMAX - 1)
+                               break;
+               }
+               *p = '\0';
+               if (temp_buf[0])
+                       printk(temp_buf);
+               mlogbuf_start = index;
+
+               mlogbuf_timestamp = 0;
+               spin_unlock_irqrestore(&mlogbuf_rlock, flags);
+       }
+}
+EXPORT_SYMBOL(ia64_mlogbuf_dump);
+
+/*
+ * Call this if system is going to down or if immediate flushing messages to
+ * console is required. (ex. recovery was failed, crash dump is going to be
+ * invoked, long-wait rendezvous etc.)
+ *  NOTE: this should be called from monarch.
+ */
+static void ia64_mlogbuf_finish(int wait)
+{
+       BREAK_LOGLEVEL(console_loglevel);
+
+       spin_lock_init(&mlogbuf_rlock);
+       ia64_mlogbuf_dump();
+       printk(KERN_EMERG "mlogbuf_finish: printing switched to urgent mode, "
+               "MCA/INIT might be dodgy or fail.\n");
+
+       if (!wait)
+               return;
+
+       /* wait for console */
+       printk("Delaying for 5 seconds...\n");
+       udelay(5*1000000);
+
+       mlogbuf_finished = 1;
+}
+EXPORT_SYMBOL(ia64_mlogbuf_finish);
+
+/*
+ * Print buffered messages from INIT context.
+ */
+static void ia64_mlogbuf_dump_from_init(void)
+{
+       if (mlogbuf_finished)
+               return;
+
+       if (mlogbuf_timestamp && (mlogbuf_timestamp + 30*HZ > jiffies)) {
+               printk(KERN_ERR "INIT: mlogbuf_dump is interrupted by INIT "
+                       " and the system seems to be messed up.\n");
+               ia64_mlogbuf_finish(0);
+               return;
+       }
+
+       if (!spin_trylock(&mlogbuf_rlock)) {
+               printk(KERN_ERR "INIT: mlogbuf_dump is interrupted by INIT. "
+                       "Generated messages other than stack dump will be "
+                       "buffered to mlogbuf and will be printed later.\n");
+               printk(KERN_ERR "INIT: If messages would not printed after "
+                       "this INIT, wait 30sec and assert INIT again.\n");
+               if (!mlogbuf_timestamp)
+                       mlogbuf_timestamp = jiffies;
+               return;
+       }
+       spin_unlock(&mlogbuf_rlock);
+       ia64_mlogbuf_dump();
+}
 
 static void inline
 ia64_mca_spin(const char *func)
 {
-       printk(KERN_EMERG "%s: spinning here, not returning to SAL\n", func);
+       if (monarch_cpu == smp_processor_id())
+               ia64_mlogbuf_finish(0);
+       mprintk(KERN_EMERG "%s: spinning here, not returning to SAL\n", func);
        while (1)
                cpu_relax();
 }
@@ -344,9 +511,6 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
        /* SAL spec states this should run w/ interrupts enabled */
        local_irq_enable();
 
-       /* Get the CPE error record and log it */
-       ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
-
        spin_lock(&cpe_history_lock);
        if (!cpe_poll_enabled && cpe_vector >= 0) {
 
@@ -375,7 +539,7 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
                        mod_timer(&cpe_poll_timer, jiffies + MIN_CPE_POLL_INTERVAL);
 
                        /* lock already released, get out now */
-                       return IRQ_HANDLED;
+                       goto out;
                } else {
                        cpe_history[index++] = now;
                        if (index == CPE_HISTORY_LENGTH)
@@ -383,6 +547,10 @@ ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs)
                }
        }
        spin_unlock(&cpe_history_lock);
+out:
+       /* Get the CPE error record and log it */
+       ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
+
        return IRQ_HANDLED;
 }
 
@@ -988,18 +1156,22 @@ ia64_wait_for_slaves(int monarch, const char *type)
        }
        if (!missing)
                goto all_in;
-       printk(KERN_INFO "OS %s slave did not rendezvous on cpu", type);
+       /*
+        * Maybe slave(s) dead. Print buffered messages immediately.
+        */
+       ia64_mlogbuf_finish(0);
+       mprintk(KERN_INFO "OS %s slave did not rendezvous on cpu", type);
        for_each_online_cpu(c) {
                if (c == monarch)
                        continue;
                if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE)
-                       printk(" %d", c);
+                       mprintk(" %d", c);
        }
-       printk("\n");
+       mprintk("\n");
        return;
 
 all_in:
-       printk(KERN_INFO "All OS %s slaves have reached rendezvous\n", type);
+       mprintk(KERN_INFO "All OS %s slaves have reached rendezvous\n", type);
        return;
 }
 
@@ -1027,10 +1199,8 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
        struct ia64_mca_notify_die nd =
                { .sos = sos, .monarch_cpu = &monarch_cpu };
 
-       oops_in_progress = 1;   /* FIXME: make printk NMI/MCA/INIT safe */
-       console_loglevel = 15;  /* make sure printks make it to console */
-       printk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d monarch=%ld\n",
-               sos->proc_state_param, cpu, sos->monarch);
+       mprintk(KERN_INFO "Entered OS MCA handler. PSP=%lx cpu=%d "
+               "monarch=%ld\n", sos->proc_state_param, cpu, sos->monarch);
 
        previous_current = ia64_mca_modify_original_stack(regs, sw, sos, "MCA");
        monarch_cpu = cpu;
@@ -1066,6 +1236,9 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
                rh->severity = sal_log_severity_corrected;
                ia64_sal_clear_state_info(SAL_INFO_TYPE_MCA);
                sos->os_status = IA64_MCA_CORRECTED;
+       } else {
+               /* Dump buffered message to console */
+               ia64_mlogbuf_finish(1);
        }
        if (notify_die(DIE_MCA_MONARCH_LEAVE, "MCA", regs, (long)&nd, 0, recover)
                        == NOTIFY_STOP)
@@ -1106,9 +1279,6 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
        /* SAL spec states this should run w/ interrupts enabled */
        local_irq_enable();
 
-       /* Get the CMC error record and log it */
-       ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);
-
        spin_lock(&cmc_history_lock);
        if (!cmc_polling_enabled) {
                int i, count = 1; /* we know 1 happened now */
@@ -1141,7 +1311,7 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
                        mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL);
 
                        /* lock already released, get out now */
-                       return IRQ_HANDLED;
+                       goto out;
                } else {
                        cmc_history[index++] = now;
                        if (index == CMC_HISTORY_LENGTH)
@@ -1149,6 +1319,10 @@ ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs)
                }
        }
        spin_unlock(&cmc_history_lock);
+out:
+       /* Get the CMC error record and log it */
+       ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC);
+
        return IRQ_HANDLED;
 }
 
@@ -1305,6 +1479,15 @@ default_monarch_init_process(struct notifier_block *self, unsigned long val, voi
        struct task_struct *g, *t;
        if (val != DIE_INIT_MONARCH_PROCESS)
                return NOTIFY_DONE;
+
+       /*
+        * FIXME: mlogbuf will brim over with INIT stack dumps.
+        * To enable show_stack from INIT, we use oops_in_progress which should
+        * be used in real oops. This would cause something wrong after INIT.
+        */
+       BREAK_LOGLEVEL(console_loglevel);
+       ia64_mlogbuf_dump_from_init();
+
        printk(KERN_ERR "Processes interrupted by INIT -");
        for_each_online_cpu(c) {
                struct ia64_sal_os_state *s;
@@ -1326,6 +1509,8 @@ default_monarch_init_process(struct notifier_block *self, unsigned long val, voi
                } while_each_thread (g, t);
                read_unlock(&tasklist_lock);
        }
+       /* FIXME: This will not restore zapped printk locks. */
+       RESTORE_LOGLEVEL(console_loglevel);
        return NOTIFY_DONE;
 }
 
@@ -1357,12 +1542,9 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
        struct ia64_mca_notify_die nd =
                { .sos = sos, .monarch_cpu = &monarch_cpu };
 
-       oops_in_progress = 1;   /* FIXME: make printk NMI/MCA/INIT safe */
-       console_loglevel = 15;  /* make sure printks make it to console */
-
        (void) notify_die(DIE_INIT_ENTER, "INIT", regs, (long)&nd, 0, 0);
 
-       printk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
+       mprintk(KERN_INFO "Entered OS INIT handler. PSP=%lx cpu=%d monarch=%ld\n",
                sos->proc_state_param, cpu, sos->monarch);
        salinfo_log_wakeup(SAL_INFO_TYPE_INIT, NULL, 0, 0);
 
@@ -1375,7 +1557,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
         * fix their proms and get their customers updated.
         */
        if (!sos->monarch && atomic_add_return(1, &slaves) == num_online_cpus()) {
-               printk(KERN_WARNING "%s: Promoting cpu %d to monarch.\n",
+               mprintk(KERN_WARNING "%s: Promoting cpu %d to monarch.\n",
                       __FUNCTION__, cpu);
                atomic_dec(&slaves);
                sos->monarch = 1;
@@ -1387,7 +1569,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
         * fix their proms and get their customers updated.
         */
        if (sos->monarch && atomic_add_return(1, &monarchs) > 1) {
-               printk(KERN_WARNING "%s: Demoting cpu %d to slave.\n",
+               mprintk(KERN_WARNING "%s: Demoting cpu %d to slave.\n",
                               __FUNCTION__, cpu);
                atomic_dec(&monarchs);
                sos->monarch = 0;
@@ -1408,7 +1590,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
                if (notify_die(DIE_INIT_SLAVE_LEAVE, "INIT", regs, (long)&nd, 0, 0)
                                == NOTIFY_STOP)
                        ia64_mca_spin(__FUNCTION__);
-               printk("Slave on cpu %d returning to normal service.\n", cpu);
+               mprintk("Slave on cpu %d returning to normal service.\n", cpu);
                set_curr_task(cpu, previous_current);
                ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE;
                atomic_dec(&slaves);
@@ -1426,7 +1608,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
         * same serial line, the user will need some time to switch out of the BMC before
         * the dump begins.
         */
-       printk("Delaying for 5 seconds...\n");
+       mprintk("Delaying for 5 seconds...\n");
        udelay(5*1000000);
        ia64_wait_for_slaves(cpu, "INIT");
        /* If nobody intercepts DIE_INIT_MONARCH_PROCESS then we drop through
@@ -1439,7 +1621,7 @@ ia64_init_handler(struct pt_regs *regs, struct switch_stack *sw,
        if (notify_die(DIE_INIT_MONARCH_LEAVE, "INIT", regs, (long)&nd, 0, 0)
                        == NOTIFY_STOP)
                ia64_mca_spin(__FUNCTION__);
-       printk("\nINIT dump complete.  Monarch on cpu %d returning to normal service.\n", cpu);
+       mprintk("\nINIT dump complete.  Monarch on cpu %d returning to normal service.\n", cpu);
        atomic_dec(&monarchs);
        set_curr_task(cpu, previous_current);
        monarch_cpu = -1;
index 96047491d1b9241fd06e196672443e1d5f16d7f1..c6b607c00deea80c4268468412b60e7fff8b5128 100644 (file)
@@ -1025,18 +1025,13 @@ ia64_old_stack:
 
 ia64_set_kernel_registers:
        add temp3=MCA_SP_OFFSET, r3
-       add temp4=MCA_SOS_OFFSET+SOS(OS_GP), r3
        mov b0=r2               // save return address
        GET_IA64_MCA_DATA(temp1)
        ;;
-       add temp4=temp4, temp1  // &struct ia64_sal_os_state.os_gp
        add r12=temp1, temp3    // kernel stack pointer on MCA/INIT stack
        add r13=temp1, r3       // set current to start of MCA/INIT stack
        add r20=temp1, r3       // physical start of MCA/INIT stack
        ;;
-       ld8 r1=[temp4]          // OS GP from SAL OS state
-       ;;
-       DATA_PA_TO_VA(r1,temp1)
        DATA_PA_TO_VA(r12,temp2)
        DATA_PA_TO_VA(r13,temp3)
        ;;
@@ -1067,6 +1062,10 @@ ia64_set_kernel_registers:
        mov cr.itir=r18
        mov cr.ifa=r13
        mov r20=IA64_TR_CURRENT_STACK
+
+       movl r17=FPSR_DEFAULT
+       ;;
+       mov.m ar.fpsr=r17                       // set ar.fpsr to kernel default value
        ;;
        itr.d dtr[r20]=r21
        ;;
index 8db6e0cedadcbc3d660bd6f5621cbc496e75b466..a45009d2bc90149e5199a97c9eff86a8d552f5b0 100644 (file)
@@ -79,14 +79,30 @@ static int
 fatal_mca(const char *fmt, ...)
 {
        va_list args;
+       char buf[256];
 
        va_start(args, fmt);
-       vprintk(fmt, args);
+       vsnprintf(buf, sizeof(buf), fmt, args);
        va_end(args);
+       ia64_mca_printk(KERN_ALERT "MCA: %s\n", buf);
 
        return MCA_NOT_RECOVERED;
 }
 
+static int
+mca_recovered(const char *fmt, ...)
+{
+       va_list args;
+       char buf[256];
+
+       va_start(args, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, args);
+       va_end(args);
+       ia64_mca_printk(KERN_INFO "MCA: %s\n", buf);
+
+       return MCA_RECOVERED;
+}
+
 /**
  * mca_page_isolate - isolate a poisoned page in order not to use it later
  * @paddr:     poisoned memory location
@@ -140,6 +156,7 @@ mca_page_isolate(unsigned long paddr)
 void
 mca_handler_bh(unsigned long paddr, void *iip, unsigned long ipsr)
 {
+       ia64_mlogbuf_dump();
        printk(KERN_ERR "OS_MCA: process [cpu %d, pid: %d, uid: %d, "
                "iip: %p, psr: 0x%lx,paddr: 0x%lx](%s) encounters MCA.\n",
                raw_smp_processor_id(), current->pid, current->uid,
@@ -440,7 +457,7 @@ recover_from_read_error(slidx_table_t *slidx,
 
        /* Is target address valid? */
        if (!pbci->tv)
-               return fatal_mca(KERN_ALERT "MCA: target address not valid\n");
+               return fatal_mca("target address not valid");
 
        /*
         * cpu read or memory-mapped io read
@@ -458,7 +475,7 @@ recover_from_read_error(slidx_table_t *slidx,
 
        /* Is minstate valid? */
        if (!peidx_bottom(peidx) || !(peidx_bottom(peidx)->valid.minstate))
-               return fatal_mca(KERN_ALERT "MCA: minstate not valid\n");
+               return fatal_mca("minstate not valid");
        psr1 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_ipsr);
        psr2 =(struct ia64_psr *)&(peidx_minstate_area(peidx)->pmsa_xpsr);
 
@@ -492,13 +509,14 @@ recover_from_read_error(slidx_table_t *slidx,
                        psr2->bn  = 1;
                        psr2->i  = 0;
 
-                       return MCA_RECOVERED;
+                       return mca_recovered("user memory corruption. "
+                               "kill affected process - recovered.");
                }
 
        }
 
-       return fatal_mca(KERN_ALERT "MCA: kernel context not recovered,"
-                         " iip 0x%lx\n", pmsa->pmsa_iip);
+       return fatal_mca("kernel context not recovered, iip 0x%lx\n",
+                        pmsa->pmsa_iip);
 }
 
 /**
@@ -584,13 +602,13 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
         * The machine check is corrected.
         */
        if (psp->cm == 1)
-               return MCA_RECOVERED;
+               return mca_recovered("machine check is already corrected.");
 
        /*
         * The error was not contained.  Software must be reset.
         */
        if (psp->us || psp->ci == 0)
-               return fatal_mca(KERN_ALERT "MCA: error not contained\n");
+               return fatal_mca("error not contained");
 
        /*
         * The cache check and bus check bits have four possible states
@@ -601,22 +619,22 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
         *    1  1      Memory error, attempt recovery
         */
        if (psp->bc == 0 || pbci == NULL)
-               return fatal_mca(KERN_ALERT "MCA: No bus check\n");
+               return fatal_mca("No bus check");
 
        /*
         * Sorry, we cannot handle so many.
         */
        if (peidx_bus_check_num(peidx) > 1)
-               return fatal_mca(KERN_ALERT "MCA: Too many bus checks\n");
+               return fatal_mca("Too many bus checks");
        /*
         * Well, here is only one bus error.
         */
        if (pbci->ib)
-               return fatal_mca(KERN_ALERT "MCA: Internal Bus error\n");
+               return fatal_mca("Internal Bus error");
        if (pbci->cc)
-               return fatal_mca(KERN_ALERT "MCA: Cache-cache error\n");
+               return fatal_mca("Cache-cache error");
        if (pbci->eb && pbci->bsi > 0)
-               return fatal_mca(KERN_ALERT "MCA: External bus check fatal status\n");
+               return fatal_mca("External bus check fatal status");
 
        /*
         * This is a local MCA and estimated as recoverble external bus error.
@@ -628,7 +646,7 @@ recover_from_processor_error(int platform, slidx_table_t *slidx,
        /*
         * On account of strange SAL error record, we cannot recover.
         */
-       return fatal_mca(KERN_ALERT "MCA: Strange SAL record\n");
+       return fatal_mca("Strange SAL record");
 }
 
 /**
@@ -657,10 +675,10 @@ mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
 
         /* Now, OS can recover when there is one processor error section */
        if (n_proc_err > 1)
-               return fatal_mca(KERN_ALERT "MCA: Too Many Errors\n");
+               return fatal_mca("Too Many Errors");
        else if (n_proc_err == 0)
-               /* Weird SAL record ... We need not to recover */
-               return fatal_mca(KERN_ALERT "MCA: Weird SAL record\n");
+               /* Weird SAL record ... We can't do anything */
+               return fatal_mca("Weird SAL record");
 
        /* Make index of processor error section */
        mca_make_peidx((sal_log_processor_info_t*)
@@ -671,7 +689,7 @@ mca_try_to_recover(void *rec, struct ia64_sal_os_state *sos)
 
        /* Check whether MCA is global or not */
        if (is_mca_global(&peidx, &pbci, sos))
-               return fatal_mca(KERN_ALERT "MCA: global MCA\n");
+               return fatal_mca("global MCA");
        
        /* Try to recover a processor error */
        return recover_from_processor_error(platform_err, &slidx, &peidx,
index 31a2e52bb16fc7c6b6af5bcfdb8a9caebd95cdb1..c85e943ba5fd93017a305b34aef00da0b56689f9 100644 (file)
@@ -118,3 +118,7 @@ struct mca_table_entry {
 
 extern const struct mca_table_entry *search_mca_tables (unsigned long addr);
 extern int mca_recover_range(unsigned long);
+extern void ia64_mca_printk(const char * fmt, ...)
+        __attribute__ ((format (printf, 1, 2)));
+extern void ia64_mlogbuf_dump(void);
+
index 7bb7696e4ce25aa3e7d0f4de86ae7970c4a3d4b5..281004ff7b00b87a46de5f91c05c90c706827474 100644 (file)
@@ -63,6 +63,9 @@
 
 #define PFM_INVALID_ACTIVATION (~0UL)
 
+#define PFM_NUM_PMC_REGS       64      /* PMC save area for ctxsw */
+#define PFM_NUM_PMD_REGS       64      /* PMD save area for ctxsw */
+
 /*
  * depth of message queue
  */
@@ -297,14 +300,17 @@ typedef struct pfm_context {
        unsigned long           ctx_reload_pmcs[4];     /* bitmask of force reload PMC on ctxsw in */
        unsigned long           ctx_used_monitors[4];   /* bitmask of monitor PMC being used */
 
-       unsigned long           ctx_pmcs[IA64_NUM_PMC_REGS];    /*  saved copies of PMC values */
+       unsigned long           ctx_pmcs[PFM_NUM_PMC_REGS];     /*  saved copies of PMC values */
 
        unsigned int            ctx_used_ibrs[1];               /* bitmask of used IBR (speedup ctxsw in) */
        unsigned int            ctx_used_dbrs[1];               /* bitmask of used DBR (speedup ctxsw in) */
        unsigned long           ctx_dbrs[IA64_NUM_DBG_REGS];    /* DBR values (cache) when not loaded */
        unsigned long           ctx_ibrs[IA64_NUM_DBG_REGS];    /* IBR values (cache) when not loaded */
 
-       pfm_counter_t           ctx_pmds[IA64_NUM_PMD_REGS]; /* software state for PMDS */
+       pfm_counter_t           ctx_pmds[PFM_NUM_PMD_REGS]; /* software state for PMDS */
+
+       unsigned long           th_pmcs[PFM_NUM_PMC_REGS];      /* PMC thread save state */
+       unsigned long           th_pmds[PFM_NUM_PMD_REGS];      /* PMD thread save state */
 
        u64                     ctx_saved_psr_up;       /* only contains psr.up value */
 
@@ -868,7 +874,6 @@ static void
 pfm_mask_monitoring(struct task_struct *task)
 {
        pfm_context_t *ctx = PFM_GET_CTX(task);
-       struct thread_struct *th = &task->thread;
        unsigned long mask, val, ovfl_mask;
        int i;
 
@@ -889,7 +894,7 @@ pfm_mask_monitoring(struct task_struct *task)
         * So in both cases, the live register contains the owner's
         * state. We can ONLY touch the PMU registers and NOT the PSR.
         *
-        * As a consequence to this call, the thread->pmds[] array
+        * As a consequence to this call, the ctx->th_pmds[] array
         * contains stale information which must be ignored
         * when context is reloaded AND monitoring is active (see
         * pfm_restart).
@@ -924,9 +929,9 @@ pfm_mask_monitoring(struct task_struct *task)
        mask = ctx->ctx_used_monitors[0] >> PMU_FIRST_COUNTER;
        for(i= PMU_FIRST_COUNTER; mask; i++, mask>>=1) {
                if ((mask & 0x1) == 0UL) continue;
-               ia64_set_pmc(i, th->pmcs[i] & ~0xfUL);
-               th->pmcs[i] &= ~0xfUL;
-               DPRINT_ovfl(("pmc[%d]=0x%lx\n", i, th->pmcs[i]));
+               ia64_set_pmc(i, ctx->th_pmcs[i] & ~0xfUL);
+               ctx->th_pmcs[i] &= ~0xfUL;
+               DPRINT_ovfl(("pmc[%d]=0x%lx\n", i, ctx->th_pmcs[i]));
        }
        /*
         * make all of this visible
@@ -943,7 +948,6 @@ static void
 pfm_restore_monitoring(struct task_struct *task)
 {
        pfm_context_t *ctx = PFM_GET_CTX(task);
-       struct thread_struct *th = &task->thread;
        unsigned long mask, ovfl_mask;
        unsigned long psr, val;
        int i, is_system;
@@ -1009,9 +1013,9 @@ pfm_restore_monitoring(struct task_struct *task)
        mask = ctx->ctx_used_monitors[0] >> PMU_FIRST_COUNTER;
        for(i= PMU_FIRST_COUNTER; mask; i++, mask>>=1) {
                if ((mask & 0x1) == 0UL) continue;
-               th->pmcs[i] = ctx->ctx_pmcs[i];
-               ia64_set_pmc(i, th->pmcs[i]);
-               DPRINT(("[%d] pmc[%d]=0x%lx\n", task->pid, i, th->pmcs[i]));
+               ctx->th_pmcs[i] = ctx->ctx_pmcs[i];
+               ia64_set_pmc(i, ctx->th_pmcs[i]);
+               DPRINT(("[%d] pmc[%d]=0x%lx\n", task->pid, i, ctx->th_pmcs[i]));
        }
        ia64_srlz_d();
 
@@ -1070,7 +1074,6 @@ pfm_restore_pmds(unsigned long *pmds, unsigned long mask)
 static inline void
 pfm_copy_pmds(struct task_struct *task, pfm_context_t *ctx)
 {
-       struct thread_struct *thread = &task->thread;
        unsigned long ovfl_val = pmu_conf->ovfl_val;
        unsigned long mask = ctx->ctx_all_pmds[0];
        unsigned long val;
@@ -1092,11 +1095,11 @@ pfm_copy_pmds(struct task_struct *task, pfm_context_t *ctx)
                        ctx->ctx_pmds[i].val = val & ~ovfl_val;
                         val &= ovfl_val;
                }
-               thread->pmds[i] = val;
+               ctx->th_pmds[i] = val;
 
                DPRINT(("pmd[%d]=0x%lx soft_val=0x%lx\n",
                        i,
-                       thread->pmds[i],
+                       ctx->th_pmds[i],
                        ctx->ctx_pmds[i].val));
        }
 }
@@ -1107,7 +1110,6 @@ pfm_copy_pmds(struct task_struct *task, pfm_context_t *ctx)
 static inline void
 pfm_copy_pmcs(struct task_struct *task, pfm_context_t *ctx)
 {
-       struct thread_struct *thread = &task->thread;
        unsigned long mask = ctx->ctx_all_pmcs[0];
        int i;
 
@@ -1115,8 +1117,8 @@ pfm_copy_pmcs(struct task_struct *task, pfm_context_t *ctx)
 
        for (i=0; mask; i++, mask>>=1) {
                /* masking 0 with ovfl_val yields 0 */
-               thread->pmcs[i] = ctx->ctx_pmcs[i];
-               DPRINT(("pmc[%d]=0x%lx\n", i, thread->pmcs[i]));
+               ctx->th_pmcs[i] = ctx->ctx_pmcs[i];
+               DPRINT(("pmc[%d]=0x%lx\n", i, ctx->th_pmcs[i]));
        }
 }
 
@@ -2860,7 +2862,6 @@ pfm_reset_regs(pfm_context_t *ctx, unsigned long *ovfl_regs, int is_long_reset)
 static int
 pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
-       struct thread_struct *thread = NULL;
        struct task_struct *task;
        pfarg_reg_t *req = (pfarg_reg_t *)arg;
        unsigned long value, pmc_pm;
@@ -2881,7 +2882,6 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
        if (state == PFM_CTX_ZOMBIE) return -EINVAL;
 
        if (is_loaded) {
-               thread = &task->thread;
                /*
                 * In system wide and when the context is loaded, access can only happen
                 * when the caller is running on the CPU being monitored by the session.
@@ -3036,7 +3036,7 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
                 *
                 * The value in ctx_pmcs[] can only be changed in pfm_write_pmcs().
                 *
-                * The value in thread->pmcs[] may be modified on overflow, i.e.,  when
+                * The value in th_pmcs[] may be modified on overflow, i.e.,  when
                 * monitoring needs to be stopped.
                 */
                if (is_monitor) CTX_USED_MONITOR(ctx, 1UL << cnum);
@@ -3050,7 +3050,7 @@ pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
                        /*
                         * write thread state
                         */
-                       if (is_system == 0) thread->pmcs[cnum] = value;
+                       if (is_system == 0) ctx->th_pmcs[cnum] = value;
 
                        /*
                         * write hardware register if we can
@@ -3102,7 +3102,6 @@ error:
 static int
 pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
-       struct thread_struct *thread = NULL;
        struct task_struct *task;
        pfarg_reg_t *req = (pfarg_reg_t *)arg;
        unsigned long value, hw_value, ovfl_mask;
@@ -3126,7 +3125,6 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
         * the owner of the local PMU.
         */
        if (likely(is_loaded)) {
-               thread = &task->thread;
                /*
                 * In system wide and when the context is loaded, access can only happen
                 * when the caller is running on the CPU being monitored by the session.
@@ -3234,7 +3232,7 @@ pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
                        /*
                         * write thread state
                         */
-                       if (is_system == 0) thread->pmds[cnum] = hw_value;
+                       if (is_system == 0) ctx->th_pmds[cnum] = hw_value;
 
                        /*
                         * write hardware register if we can
@@ -3300,7 +3298,6 @@ abort_mission:
 static int
 pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
-       struct thread_struct *thread = NULL;
        struct task_struct *task;
        unsigned long val = 0UL, lval, ovfl_mask, sval;
        pfarg_reg_t *req = (pfarg_reg_t *)arg;
@@ -3324,7 +3321,6 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
        if (state == PFM_CTX_ZOMBIE) return -EINVAL;
 
        if (likely(is_loaded)) {
-               thread = &task->thread;
                /*
                 * In system wide and when the context is loaded, access can only happen
                 * when the caller is running on the CPU being monitored by the session.
@@ -3386,7 +3382,7 @@ pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
                         * if context is zombie, then task does not exist anymore.
                         * In this case, we use the full value saved in the context (pfm_flush_regs()).
                         */
-                       val = is_loaded ? thread->pmds[cnum] : 0UL;
+                       val = is_loaded ? ctx->th_pmds[cnum] : 0UL;
                }
                rd_func = pmu_conf->pmd_desc[cnum].read_check;
 
@@ -4355,8 +4351,8 @@ pfm_context_load(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
        pfm_copy_pmds(task, ctx);
        pfm_copy_pmcs(task, ctx);
 
-       pmcs_source = thread->pmcs;
-       pmds_source = thread->pmds;
+       pmcs_source = ctx->th_pmcs;
+       pmds_source = ctx->th_pmds;
 
        /*
         * always the case for system-wide
@@ -5865,14 +5861,12 @@ void
 pfm_save_regs(struct task_struct *task)
 {
        pfm_context_t *ctx;
-       struct thread_struct *t;
        unsigned long flags;
        u64 psr;
 
 
        ctx = PFM_GET_CTX(task);
        if (ctx == NULL) return;
-       t = &task->thread;
 
        /*
         * we always come here with interrupts ALREADY disabled by
@@ -5930,19 +5924,19 @@ pfm_save_regs(struct task_struct *task)
         * guarantee we will be schedule at that same
         * CPU again.
         */
-       pfm_save_pmds(t->pmds, ctx->ctx_used_pmds[0]);
+       pfm_save_pmds(ctx->th_pmds, ctx->ctx_used_pmds[0]);
 
        /*
         * save pmc0 ia64_srlz_d() done in pfm_save_pmds()
         * we will need it on the restore path to check
         * for pending overflow.
         */
-       t->pmcs[0] = ia64_get_pmc(0);
+       ctx->th_pmcs[0] = ia64_get_pmc(0);
 
        /*
         * unfreeze PMU if had pending overflows
         */
-       if (t->pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
+       if (ctx->th_pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
 
        /*
         * finally, allow context access.
@@ -5987,7 +5981,6 @@ static void
 pfm_lazy_save_regs (struct task_struct *task)
 {
        pfm_context_t *ctx;
-       struct thread_struct *t;
        unsigned long flags;
 
        { u64 psr  = pfm_get_psr();
@@ -5995,7 +5988,6 @@ pfm_lazy_save_regs (struct task_struct *task)
        }
 
        ctx = PFM_GET_CTX(task);
-       t   = &task->thread;
 
        /*
         * we need to mask PMU overflow here to
@@ -6020,19 +6012,19 @@ pfm_lazy_save_regs (struct task_struct *task)
        /*
         * save all the pmds we use
         */
-       pfm_save_pmds(t->pmds, ctx->ctx_used_pmds[0]);
+       pfm_save_pmds(ctx->th_pmds, ctx->ctx_used_pmds[0]);
 
        /*
         * save pmc0 ia64_srlz_d() done in pfm_save_pmds()
         * it is needed to check for pended overflow
         * on the restore path
         */
-       t->pmcs[0] = ia64_get_pmc(0);
+       ctx->th_pmcs[0] = ia64_get_pmc(0);
 
        /*
         * unfreeze PMU if had pending overflows
         */
-       if (t->pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
+       if (ctx->th_pmcs[0] & ~0x1UL) pfm_unfreeze_pmu();
 
        /*
         * now get can unmask PMU interrupts, they will
@@ -6051,7 +6043,6 @@ void
 pfm_load_regs (struct task_struct *task)
 {
        pfm_context_t *ctx;
-       struct thread_struct *t;
        unsigned long pmc_mask = 0UL, pmd_mask = 0UL;
        unsigned long flags;
        u64 psr, psr_up;
@@ -6062,11 +6053,10 @@ pfm_load_regs (struct task_struct *task)
 
        BUG_ON(GET_PMU_OWNER());
 
-       t     = &task->thread;
        /*
         * possible on unload
         */
-       if (unlikely((t->flags & IA64_THREAD_PM_VALID) == 0)) return;
+       if (unlikely((task->thread.flags & IA64_THREAD_PM_VALID) == 0)) return;
 
        /*
         * we always come here with interrupts ALREADY disabled by
@@ -6148,21 +6138,21 @@ pfm_load_regs (struct task_struct *task)
         *
         * XXX: optimize here
         */
-       if (pmd_mask) pfm_restore_pmds(t->pmds, pmd_mask);
-       if (pmc_mask) pfm_restore_pmcs(t->pmcs, pmc_mask);
+       if (pmd_mask) pfm_restore_pmds(ctx->th_pmds, pmd_mask);
+       if (pmc_mask) pfm_restore_pmcs(ctx->th_pmcs, pmc_mask);
 
        /*
         * check for pending overflow at the time the state
         * was saved.
         */
-       if (unlikely(PMC0_HAS_OVFL(t->pmcs[0]))) {
+       if (unlikely(PMC0_HAS_OVFL(ctx->th_pmcs[0]))) {
                /*
                 * reload pmc0 with the overflow information
                 * On McKinley PMU, this will trigger a PMU interrupt
                 */
-               ia64_set_pmc(0, t->pmcs[0]);
+               ia64_set_pmc(0, ctx->th_pmcs[0]);
                ia64_srlz_d();
-               t->pmcs[0] = 0UL;
+               ctx->th_pmcs[0] = 0UL;
 
                /*
                 * will replay the PMU interrupt
@@ -6215,7 +6205,6 @@ pfm_load_regs (struct task_struct *task)
 void
 pfm_load_regs (struct task_struct *task)
 {
-       struct thread_struct *t;
        pfm_context_t *ctx;
        struct task_struct *owner;
        unsigned long pmd_mask, pmc_mask;
@@ -6224,7 +6213,6 @@ pfm_load_regs (struct task_struct *task)
 
        owner = GET_PMU_OWNER();
        ctx   = PFM_GET_CTX(task);
-       t     = &task->thread;
        psr   = pfm_get_psr();
 
        BUG_ON(psr & (IA64_PSR_UP|IA64_PSR_PP));
@@ -6287,22 +6275,22 @@ pfm_load_regs (struct task_struct *task)
         */
        pmc_mask = ctx->ctx_all_pmcs[0];
 
-       pfm_restore_pmds(t->pmds, pmd_mask);
-       pfm_restore_pmcs(t->pmcs, pmc_mask);
+       pfm_restore_pmds(ctx->th_pmds, pmd_mask);
+       pfm_restore_pmcs(ctx->th_pmcs, pmc_mask);
 
        /*
         * check for pending overflow at the time the state
         * was saved.
         */
-       if (unlikely(PMC0_HAS_OVFL(t->pmcs[0]))) {
+       if (unlikely(PMC0_HAS_OVFL(ctx->th_pmcs[0]))) {
                /*
                 * reload pmc0 with the overflow information
                 * On McKinley PMU, this will trigger a PMU interrupt
                 */
-               ia64_set_pmc(0, t->pmcs[0]);
+               ia64_set_pmc(0, ctx->th_pmcs[0]);
                ia64_srlz_d();
 
-               t->pmcs[0] = 0UL;
+               ctx->th_pmcs[0] = 0UL;
 
                /*
                 * will replay the PMU interrupt
@@ -6377,11 +6365,11 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
                 */
                pfm_unfreeze_pmu();
        } else {
-               pmc0 = task->thread.pmcs[0];
+               pmc0 = ctx->th_pmcs[0];
                /*
                 * clear whatever overflow status bits there were
                 */
-               task->thread.pmcs[0] = 0;
+               ctx->th_pmcs[0] = 0;
        }
        ovfl_val = pmu_conf->ovfl_val;
        /*
@@ -6402,7 +6390,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
                /*
                 * can access PMU always true in system wide mode
                 */
-               val = pmd_val = can_access_pmu ? ia64_get_pmd(i) : task->thread.pmds[i];
+               val = pmd_val = can_access_pmu ? ia64_get_pmd(i) : ctx->th_pmds[i];
 
                if (PMD_IS_COUNTING(i)) {
                        DPRINT(("[%d] pmd[%d] ctx_pmd=0x%lx hw_pmd=0x%lx\n",
@@ -6434,7 +6422,7 @@ pfm_flush_pmds(struct task_struct *task, pfm_context_t *ctx)
 
                DPRINT(("[%d] ctx_pmd[%d]=0x%lx  pmd_val=0x%lx\n", task->pid, i, val, pmd_val));
 
-               if (is_self) task->thread.pmds[i] = pmd_val;
+               if (is_self) ctx->th_pmds[i] = pmd_val;
 
                ctx->ctx_pmds[i].val = val;
        }
@@ -6678,7 +6666,7 @@ pfm_init(void)
               ffz(pmu_conf->ovfl_val));
 
        /* sanity check */
-       if (pmu_conf->num_pmds >= IA64_NUM_PMD_REGS || pmu_conf->num_pmcs >= IA64_NUM_PMC_REGS) {
+       if (pmu_conf->num_pmds >= PFM_NUM_PMD_REGS || pmu_conf->num_pmcs >= PFM_NUM_PMC_REGS) {
                printk(KERN_ERR "perfmon: not enough pmc/pmd, perfmon disabled\n");
                pmu_conf = NULL;
                return -1;
@@ -6753,7 +6741,6 @@ void
 dump_pmu_state(const char *from)
 {
        struct task_struct *task;
-       struct thread_struct *t;
        struct pt_regs *regs;
        pfm_context_t *ctx;
        unsigned long psr, dcr, info, flags;
@@ -6798,16 +6785,14 @@ dump_pmu_state(const char *from)
        ia64_psr(regs)->up = 0;
        ia64_psr(regs)->pp = 0;
 
-       t = &current->thread;
-
        for (i=1; PMC_IS_LAST(i) == 0; i++) {
                if (PMC_IS_IMPL(i) == 0) continue;
-               printk("->CPU%d pmc[%d]=0x%lx thread_pmc[%d]=0x%lx\n", this_cpu, i, ia64_get_pmc(i), i, t->pmcs[i]);
+               printk("->CPU%d pmc[%d]=0x%lx thread_pmc[%d]=0x%lx\n", this_cpu, i, ia64_get_pmc(i), i, ctx->th_pmcs[i]);
        }
 
        for (i=1; PMD_IS_LAST(i) == 0; i++) {
                if (PMD_IS_IMPL(i) == 0) continue;
-               printk("->CPU%d pmd[%d]=0x%lx thread_pmd[%d]=0x%lx\n", this_cpu, i, ia64_get_pmd(i), i, t->pmds[i]);
+               printk("->CPU%d pmd[%d]=0x%lx thread_pmd[%d]=0x%lx\n", this_cpu, i, ia64_get_pmd(i), i, ctx->th_pmds[i]);
        }
 
        if (ctx) {
index 9065f0f01ba3e7f70b48abf36af96cf46b205514..e63b8ca5344a202d85b8cb1d25a4edb08c486894 100644 (file)
@@ -266,6 +266,7 @@ salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe)
 /* Check for outstanding MCA/INIT records every minute (arbitrary) */
 #define SALINFO_TIMER_DELAY (60*HZ)
 static struct timer_list salinfo_timer;
+extern void ia64_mlogbuf_dump(void);
 
 static void
 salinfo_timeout_check(struct salinfo_data *data)
@@ -283,6 +284,7 @@ salinfo_timeout_check(struct salinfo_data *data)
 static void
 salinfo_timeout (unsigned long arg)
 {
+       ia64_mlogbuf_dump();
        salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA);
        salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_INIT);
        salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY;
@@ -332,6 +334,8 @@ retry:
        if (cpu == -1)
                goto retry;
 
+       ia64_mlogbuf_dump();
+
        /* for next read, start checking at next CPU */
        data->cpu_check = cpu;
        if (++data->cpu_check == NR_CPUS)
index 7ad0d9cc6db65c1503cc3a69259954633c6c5991..84f93c0f2c666b15d3f70c3df47c3c17a5949ad0 100644 (file)
@@ -509,7 +509,7 @@ show_cpuinfo (struct seq_file *m, void *v)
                { 1UL << 1, "spontaneous deferral"},
                { 1UL << 2, "16-byte atomic ops" }
        };
-       char family[32], features[128], *cp, sep;
+       char features[128], *cp, sep;
        struct cpuinfo_ia64 *c = v;
        unsigned long mask;
        unsigned long proc_freq;
@@ -517,12 +517,6 @@ show_cpuinfo (struct seq_file *m, void *v)
 
        mask = c->features;
 
-       switch (c->family) {
-             case 0x07:        memcpy(family, "Itanium", 8); break;
-             case 0x1f:        memcpy(family, "Itanium 2", 10); break;
-             default:          sprintf(family, "%u", c->family); break;
-       }
-
        /* build the feature string: */
        memcpy(features, " standard", 10);
        cp = features;
@@ -553,8 +547,9 @@ show_cpuinfo (struct seq_file *m, void *v)
                   "processor  : %d\n"
                   "vendor     : %s\n"
                   "arch       : IA-64\n"
-                  "family     : %s\n"
+                  "family     : %u\n"
                   "model      : %u\n"
+                  "model name : %s\n"
                   "revision   : %u\n"
                   "archrev    : %u\n"
                   "features   :%s\n"   /* don't change this---it _is_ right! */
@@ -563,7 +558,8 @@ show_cpuinfo (struct seq_file *m, void *v)
                   "cpu MHz    : %lu.%06lu\n"
                   "itc MHz    : %lu.%06lu\n"
                   "BogoMIPS   : %lu.%02lu\n",
-                  cpunum, c->vendor, family, c->model, c->revision, c->archrev,
+                  cpunum, c->vendor, c->family, c->model,
+                  c->model_name, c->revision, c->archrev,
                   features, c->ppn, c->number,
                   proc_freq / 1000, proc_freq % 1000,
                   c->itc_freq / 1000000, c->itc_freq % 1000000,
@@ -611,6 +607,31 @@ struct seq_operations cpuinfo_op = {
        .show =         show_cpuinfo
 };
 
+static char brandname[128];
+
+static char * __cpuinit
+get_model_name(__u8 family, __u8 model)
+{
+       char brand[128];
+
+       if (ia64_pal_get_brand_info(brand)) {
+               if (family == 0x7)
+                       memcpy(brand, "Merced", 7);
+               else if (family == 0x1f) switch (model) {
+                       case 0: memcpy(brand, "McKinley", 9); break;
+                       case 1: memcpy(brand, "Madison", 8); break;
+                       case 2: memcpy(brand, "Madison up to 9M cache", 23); break;
+               } else
+                       memcpy(brand, "Unknown", 8);
+       }
+       if (brandname[0] == '\0')
+               return strcpy(brandname, brand);
+       else if (strcmp(brandname, brand) == 0)
+               return brandname;
+       else
+               return kstrdup(brand, GFP_KERNEL);
+}
+
 static void __cpuinit
 identify_cpu (struct cpuinfo_ia64 *c)
 {
@@ -640,7 +661,6 @@ identify_cpu (struct cpuinfo_ia64 *c)
        pal_status_t status;
        unsigned long impl_va_msb = 50, phys_addr_size = 44;    /* Itanium defaults */
        int i;
-
        for (i = 0; i < 5; ++i)
                cpuid.bits[i] = ia64_get_cpuid(i);
 
@@ -663,6 +683,7 @@ identify_cpu (struct cpuinfo_ia64 *c)
        c->family = cpuid.field.family;
        c->archrev = cpuid.field.archrev;
        c->features = cpuid.field.features;
+       c->model_name = get_model_name(c->family, c->model);
 
        status = ia64_pal_vm_summary(&vm1, &vm2);
        if (status == PAL_STATUS_SUCCESS) {
index 6203ed4ec8cfadbab3a6d77f055633ad055cc8c8..f7d7f5668144fcec8e76bcadb66c5df27aad17d9 100644 (file)
@@ -879,3 +879,27 @@ identify_siblings(struct cpuinfo_ia64 *c)
        c->core_id = info.log1_cid;
        c->thread_id = info.log1_tid;
 }
+
+/*
+ * returns non zero, if multi-threading is enabled
+ * on at least one physical package. Due to hotplug cpu
+ * and (maxcpus=), all threads may not necessarily be enabled
+ * even though the processor supports multi-threading.
+ */
+int is_multithreading_enabled(void)
+{
+       int i, j;
+
+       for_each_present_cpu(i) {
+               for_each_present_cpu(j) {
+                       if (j == i)
+                               continue;
+                       if ((cpu_data(j)->socket_id == cpu_data(i)->socket_id)) {
+                               if (cpu_data(j)->core_id == cpu_data(i)->core_id)
+                                       return 1;
+                       }
+               }
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(is_multithreading_enabled);
index 05bdf7affb431742a7c0f7ea8c167bea6300c530..5629b45e89c6bc50892c4a8e69b66d0f0be67d86 100644 (file)
@@ -36,9 +36,7 @@ int arch_register_cpu(int num)
         */
        if (!can_cpei_retarget() && is_cpu_cpei_target(num))
                sysfs_cpus[num].cpu.no_control = 1;
-#ifdef CONFIG_NUMA
        map_cpu_to_node(num, node_cpuid[num].nid);
-#endif
 #endif
 
        return register_cpu(&sysfs_cpus[num].cpu, num);
index 5b0d5f64a9b11d7fff31532595f5fbb00a8c036a..b3b2e389d6b2e2abc690f37e7e62bb39127afaba 100644 (file)
@@ -184,7 +184,9 @@ SECTIONS
          *(.data.gate)
          __stop_gate_section = .;
        }
-  . = ALIGN(PAGE_SIZE);                /* make sure the gate page doesn't expose kernel data */
+  . = ALIGN(PAGE_SIZE);                /* make sure the gate page doesn't expose
+                                * kernel data
+                                */
 
   .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET)
         { *(.data.read_mostly) }
@@ -202,7 +204,9 @@ SECTIONS
                *(.data.percpu)
                __per_cpu_end = .;
        }
-  . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits into percpu page size */
+  . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits
+                                                * into percpu page size
+                                                */
 
   data : { } :data
   .data : AT(ADDR(.data) - LOAD_OFFSET)
index e004143ba86b7f22ce19d8a002a3cbd944b94c7a..daf977ff2920e2c88aee4c6398a7d135bc22d802 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/mca.h>
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-static unsigned long num_dma_physpages;
 static unsigned long max_gap;
 #endif
 
@@ -41,10 +40,11 @@ show_mem (void)
        int i, total = 0, reserved = 0;
        int shared = 0, cached = 0;
 
-       printk("Mem-info:\n");
+       printk(KERN_INFO "Mem-info:\n");
        show_free_areas();
 
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+       printk(KERN_INFO "Free swap:       %6ldkB\n",
+              nr_swap_pages<<(PAGE_SHIFT-10));
        i = max_mapnr;
        for (i = 0; i < max_mapnr; i++) {
                if (!pfn_valid(i)) {
@@ -63,12 +63,12 @@ show_mem (void)
                else if (page_count(mem_map + i))
                        shared += page_count(mem_map + i) - 1;
        }
-       printk("%d pages of RAM\n", total);
-       printk("%d reserved pages\n", reserved);
-       printk("%d pages shared\n", shared);
-       printk("%d pages swap cached\n", cached);
-       printk("%ld pages in page table cache\n",
-               pgtable_quicklist_total_size());
+       printk(KERN_INFO "%d pages of RAM\n", total);
+       printk(KERN_INFO "%d reserved pages\n", reserved);
+       printk(KERN_INFO "%d pages shared\n", shared);
+       printk(KERN_INFO "%d pages swap cached\n", cached);
+       printk(KERN_INFO "%ld pages in page table cache\n",
+              pgtable_quicklist_total_size());
 }
 
 /* physical address where the bootmem map is located */
@@ -218,18 +218,6 @@ count_pages (u64 start, u64 end, void *arg)
        return 0;
 }
 
-#ifdef CONFIG_VIRTUAL_MEM_MAP
-static int
-count_dma_pages (u64 start, u64 end, void *arg)
-{
-       unsigned long *count = arg;
-
-       if (start < MAX_DMA_ADDRESS)
-               *count += (min(end, MAX_DMA_ADDRESS) - start) >> PAGE_SHIFT;
-       return 0;
-}
-#endif
-
 /*
  * Set up the page tables.
  */
@@ -238,45 +226,22 @@ void __init
 paging_init (void)
 {
        unsigned long max_dma;
-       unsigned long zones_size[MAX_NR_ZONES];
-#ifdef CONFIG_VIRTUAL_MEM_MAP
-       unsigned long zholes_size[MAX_NR_ZONES];
-#endif
-
-       /* initialize mem_map[] */
-
-       memset(zones_size, 0, sizeof(zones_size));
+       unsigned long nid = 0;
+       unsigned long max_zone_pfns[MAX_NR_ZONES];
 
        num_physpages = 0;
        efi_memmap_walk(count_pages, &num_physpages);
 
        max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+       max_zone_pfns[ZONE_DMA] = max_dma;
+       max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
-       memset(zholes_size, 0, sizeof(zholes_size));
-
-       num_dma_physpages = 0;
-       efi_memmap_walk(count_dma_pages, &num_dma_physpages);
-
-       if (max_low_pfn < max_dma) {
-               zones_size[ZONE_DMA] = max_low_pfn;
-               zholes_size[ZONE_DMA] = max_low_pfn - num_dma_physpages;
-       } else {
-               zones_size[ZONE_DMA] = max_dma;
-               zholes_size[ZONE_DMA] = max_dma - num_dma_physpages;
-               if (num_physpages > num_dma_physpages) {
-                       zones_size[ZONE_NORMAL] = max_low_pfn - max_dma;
-                       zholes_size[ZONE_NORMAL] =
-                               ((max_low_pfn - max_dma) -
-                                (num_physpages - num_dma_physpages));
-               }
-       }
-
+       efi_memmap_walk(register_active_ranges, &nid);
        efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
        if (max_gap < LARGE_GAP) {
                vmem_map = (struct page *) 0;
-               free_area_init_node(0, NODE_DATA(0), zones_size, 0,
-                                   zholes_size);
+               free_area_init_nodes(max_zone_pfns);
        } else {
                unsigned long map_size;
 
@@ -288,20 +253,19 @@ paging_init (void)
                vmem_map = (struct page *) vmalloc_end;
                efi_memmap_walk(create_mem_map_page_table, NULL);
 
-               NODE_DATA(0)->node_mem_map = vmem_map;
-               free_area_init_node(0, NODE_DATA(0), zones_size,
-                                   0, zholes_size);
+               /*
+                * alloc_node_mem_map makes an adjustment for mem_map
+                * which isn't compatible with vmem_map.
+                */
+               NODE_DATA(0)->node_mem_map = vmem_map +
+                       find_min_pfn_with_active_regions();
+               free_area_init_nodes(max_zone_pfns);
 
                printk("Virtual mem_map starts at 0x%p\n", mem_map);
        }
 #else /* !CONFIG_VIRTUAL_MEM_MAP */
-       if (max_low_pfn < max_dma)
-               zones_size[ZONE_DMA] = max_low_pfn;
-       else {
-               zones_size[ZONE_DMA] = max_dma;
-               zones_size[ZONE_NORMAL] = max_low_pfn - max_dma;
-       }
-       free_area_init(zones_size);
+       add_active_range(0, 0, max_low_pfn);
+       free_area_init_nodes(max_zone_pfns);
 #endif /* !CONFIG_VIRTUAL_MEM_MAP */
        zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
 }
index d260bffa01ab9ffd5949eec9f411554dc84ae9a7..d497b6b0f5b2c08d4be5cd50478399db993a2dc8 100644 (file)
@@ -547,15 +547,16 @@ void show_mem(void)
        unsigned long total_present = 0;
        pg_data_t *pgdat;
 
-       printk("Mem-info:\n");
+       printk(KERN_INFO "Mem-info:\n");
        show_free_areas();
-       printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+       printk(KERN_INFO "Free swap:       %6ldkB\n",
+              nr_swap_pages<<(PAGE_SHIFT-10));
+       printk(KERN_INFO "Node memory in pages:\n");
        for_each_online_pgdat(pgdat) {
                unsigned long present;
                unsigned long flags;
                int shared = 0, cached = 0, reserved = 0;
 
-               printk("Node ID: %d\n", pgdat->node_id);
                pgdat_resize_lock(pgdat, &flags);
                present = pgdat->node_present_pages;
                for(i = 0; i < pgdat->node_spanned_pages; i++) {
@@ -579,18 +580,17 @@ void show_mem(void)
                total_reserved += reserved;
                total_cached += cached;
                total_shared += shared;
-               printk("\t%ld pages of RAM\n", present);
-               printk("\t%d reserved pages\n", reserved);
-               printk("\t%d pages shared\n", shared);
-               printk("\t%d pages swap cached\n", cached);
+               printk(KERN_INFO "Node %4d:  RAM: %11ld, rsvd: %8d, "
+                      "shrd: %10d, swpd: %10d\n", pgdat->node_id,
+                      present, reserved, shared, cached);
        }
-       printk("%ld pages of RAM\n", total_present);
-       printk("%d reserved pages\n", total_reserved);
-       printk("%d pages shared\n", total_shared);
-       printk("%d pages swap cached\n", total_cached);
-       printk("Total of %ld pages in page table cache\n",
-               pgtable_quicklist_total_size());
-       printk("%d free buffer pages\n", nr_free_buffer_pages());
+       printk(KERN_INFO "%ld pages of RAM\n", total_present);
+       printk(KERN_INFO "%d reserved pages\n", total_reserved);
+       printk(KERN_INFO "%d pages shared\n", total_shared);
+       printk(KERN_INFO "%d pages swap cached\n", total_cached);
+       printk(KERN_INFO "Total of %ld pages in page table cache\n",
+              pgtable_quicklist_total_size());
+       printk(KERN_INFO "%d free buffer pages\n", nr_free_buffer_pages());
 }
 
 /**
@@ -654,6 +654,7 @@ static __init int count_node_pages(unsigned long start, unsigned long len, int n
 {
        unsigned long end = start + len;
 
+       add_active_range(node, start >> PAGE_SHIFT, end >> PAGE_SHIFT);
        mem_data[node].num_physpages += len >> PAGE_SHIFT;
        if (start <= __pa(MAX_DMA_ADDRESS))
                mem_data[node].num_dma_physpages +=
@@ -678,10 +679,10 @@ static __init int count_node_pages(unsigned long start, unsigned long len, int n
 void __init paging_init(void)
 {
        unsigned long max_dma;
-       unsigned long zones_size[MAX_NR_ZONES];
-       unsigned long zholes_size[MAX_NR_ZONES];
        unsigned long pfn_offset = 0;
+       unsigned long max_pfn = 0;
        int node;
+       unsigned long max_zone_pfns[MAX_NR_ZONES];
 
        max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 
@@ -698,47 +699,20 @@ void __init paging_init(void)
 #endif
 
        for_each_online_node(node) {
-               memset(zones_size, 0, sizeof(zones_size));
-               memset(zholes_size, 0, sizeof(zholes_size));
-
                num_physpages += mem_data[node].num_physpages;
-
-               if (mem_data[node].min_pfn >= max_dma) {
-                       /* All of this node's memory is above ZONE_DMA */
-                       zones_size[ZONE_NORMAL] = mem_data[node].max_pfn -
-                               mem_data[node].min_pfn;
-                       zholes_size[ZONE_NORMAL] = mem_data[node].max_pfn -
-                               mem_data[node].min_pfn -
-                               mem_data[node].num_physpages;
-               } else if (mem_data[node].max_pfn < max_dma) {
-                       /* All of this node's memory is in ZONE_DMA */
-                       zones_size[ZONE_DMA] = mem_data[node].max_pfn -
-                               mem_data[node].min_pfn;
-                       zholes_size[ZONE_DMA] = mem_data[node].max_pfn -
-                               mem_data[node].min_pfn -
-                               mem_data[node].num_dma_physpages;
-               } else {
-                       /* This node has memory in both zones */
-                       zones_size[ZONE_DMA] = max_dma -
-                               mem_data[node].min_pfn;
-                       zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] -
-                               mem_data[node].num_dma_physpages;
-                       zones_size[ZONE_NORMAL] = mem_data[node].max_pfn -
-                               max_dma;
-                       zholes_size[ZONE_NORMAL] = zones_size[ZONE_NORMAL] -
-                               (mem_data[node].num_physpages -
-                                mem_data[node].num_dma_physpages);
-               }
-
                pfn_offset = mem_data[node].min_pfn;
 
 #ifdef CONFIG_VIRTUAL_MEM_MAP
                NODE_DATA(node)->node_mem_map = vmem_map + pfn_offset;
 #endif
-               free_area_init_node(node, NODE_DATA(node), zones_size,
-                                   pfn_offset, zholes_size);
+               if (mem_data[node].max_pfn > max_pfn)
+                       max_pfn = mem_data[node].max_pfn;
        }
 
+       max_zone_pfns[ZONE_DMA] = max_dma;
+       max_zone_pfns[ZONE_NORMAL] = max_pfn;
+       free_area_init_nodes(max_zone_pfns);
+
        zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page));
 }
 
index 30617ccb4f7e69bc5e412dbc63aae8405e1a8691..ff87a5cba399f873348858fa7775a608ab2c3fb7 100644 (file)
@@ -593,6 +593,18 @@ find_largest_hole (u64 start, u64 end, void *arg)
        last_end = end;
        return 0;
 }
+
+int __init
+register_active_ranges(u64 start, u64 end, void *nid)
+{
+       BUG_ON(nid == NULL);
+       BUG_ON(*(unsigned long *)nid >= MAX_NUMNODES);
+
+       add_active_range(*(unsigned long *)nid,
+                               __pa(start) >> PAGE_SHIFT,
+                               __pa(end) >> PAGE_SHIFT);
+       return 0;
+}
 #endif /* CONFIG_VIRTUAL_MEM_MAP */
 
 static int __init
index 60b45e79f080dbf11f60e7deb362c1efd37cbc0f..15c7c670da39e042c0173467e289be1a737efca7 100644 (file)
@@ -562,7 +562,8 @@ pcibios_enable_device (struct pci_dev *dev, int mask)
 void
 pcibios_disable_device (struct pci_dev *dev)
 {
-       acpi_pci_irq_disable(dev);
+       if (dev->is_enabled)
+               acpi_pci_irq_disable(dev);
 }
 
 void
index 27dee4584061ffc918f1d9450262e7124ab8fee6..7f73ad4408aaee3ad8977ad1ef2d1a89302cfbe5 100644 (file)
@@ -277,8 +277,7 @@ bte_result_t bte_unaligned_copy(u64 src, u64 dest, u64 len, u64 mode)
        }
 
        /* temporary buffer used during unaligned transfers */
-       bteBlock_unaligned = kmalloc(len + 3 * L1_CACHE_BYTES,
-                                    GFP_KERNEL | GFP_DMA);
+       bteBlock_unaligned = kmalloc(len + 3 * L1_CACHE_BYTES, GFP_KERNEL);
        if (bteBlock_unaligned == NULL) {
                return BTEFAIL_NOTAVAIL;
        }
index 330f6abc7703c0302db441be299eafc842a3ff52..30750c54bdf5169564855012899f6e2acb42299d 100644 (file)
@@ -126,7 +126,7 @@ config BASLER_EXCITE
        select IRQ_CPU
        select IRQ_CPU_RM7K
        select IRQ_CPU_RM9K
-       select SERIAL_RM9000
+       select MIPS_RM9122
        select SYS_HAS_CPU_RM9000
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
@@ -203,26 +203,6 @@ config MIPS_EV64120
          <http://www.marvell.com/>.  Say Y here if you wish to build a
          kernel for this platform.
 
-config MIPS_EV96100
-       bool "Galileo EV96100 Evaluation board (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-       select DMA_NONCOHERENT
-       select HW_HAS_PCI
-       select IRQ_CPU
-       select MIPS_GT96100
-       select RM7000_CPU_SCACHE
-       select SWAP_IO_SPACE
-       select SYS_HAS_CPU_R5000
-       select SYS_HAS_CPU_RM7000
-       select SYS_SUPPORTS_32BIT_KERNEL
-       select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-       select SYS_SUPPORTS_BIG_ENDIAN
-       help
-         This is an evaluation board based on the Galileo GT-96100 LAN/WAN
-         communications controllers containing a MIPS R5000 compatible core
-         running at 83MHz. Their website is <http://www.marvell.com/>. Say Y
-         here if you wish to build a kernel for this platform.
-
 config MIPS_IVR
        bool "Globespan IVR board"
        select DMA_NONCOHERENT
@@ -974,6 +954,12 @@ config MIPS_TX3927
        bool
        select HAS_TXX9_SERIAL
 
+config MIPS_RM9122
+       bool
+       select SERIAL_RM9000
+       select GPI_RM9000
+       select WDT_RM9000
+
 config PCI_MARVELL
        bool
 
@@ -1024,6 +1010,15 @@ config EMMA2RH
        depends on MARKEINS
        default y
 
+config SERIAL_RM9000
+       bool
+
+config GPI_RM9000
+       bool
+
+config WDT_RM9000
+       bool
+
 #
 # Unfortunately not all GT64120 systems run the chip at the same clock.
 # As the user for the clock rate and try to minimize the available options.
@@ -1054,10 +1049,6 @@ config AU1X00_USB_DEVICE
        depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000
        default n
 
-config MIPS_GT96100
-       bool
-       select MIPS_GT64120
-
 config IT8172_CIR
        bool
        depends on MIPS_ITE8172 || MIPS_IVR
@@ -1527,6 +1518,7 @@ config MIPS_MT_SMTC
        select CPU_MIPSR2_SRS
        select MIPS_MT
        select SMP
+       select SYS_SUPPORTS_SMP
        help
          This is a kernel model which is known a SMTC or lately has been
          marketesed into SMVP.
@@ -1538,6 +1530,7 @@ config MIPS_MT_SMP
        select CPU_MIPSR2_SRS
        select MIPS_MT
        select SMP
+       select SYS_SUPPORTS_SMP
        help
          This is a kernel model which is also known a VSMP or lately
          has been marketesed into SMVP.
@@ -1649,9 +1642,7 @@ config GENERIC_IRQ_PROBE
        default y
 
 config IRQ_PER_CPU
-       depends on SMP
        bool
-       default y
 
 #
 # - Highmem only makes sense for the 32-bit kernel.
@@ -1719,6 +1710,7 @@ source "mm/Kconfig"
 config SMP
        bool "Multi-Processing support"
        depends on SYS_SUPPORTS_SMP
+       select IRQ_PER_CPU
        help
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
index d333ce4ba26b54dfc5b188c9cd5a856c90099da8..e521826b423459bc5e3c9ff018954420f346403c 100644 (file)
@@ -279,13 +279,6 @@ core-$(CONFIG_MIPS_EV64120)        += arch/mips/gt64120/common/
 cflags-$(CONFIG_MIPS_EV64120)  += -Iinclude/asm-mips/mach-ev64120
 load-$(CONFIG_MIPS_EV64120)    += 0xffffffff80100000
 
-#
-# Galileo EV96100 Board
-#
-core-$(CONFIG_MIPS_EV96100)    += arch/mips/galileo-boards/ev96100/
-cflags-$(CONFIG_MIPS_EV96100)  += -Iinclude/asm-mips/mach-ev96100
-load-$(CONFIG_MIPS_EV96100)    += 0xffffffff80100000
-
 #
 # Wind River PPMC Board (4KC + GT64120)
 #
@@ -330,6 +323,7 @@ load-$(CONFIG_MIPS_MALTA)   += 0xffffffff80100000
 # MIPS SEAD board
 #
 core-$(CONFIG_MIPS_SEAD)       += arch/mips/mips-boards/sead/
+cflags-$(CONFIG_MIPS_SEAD)     += -Iinclude/asm-mips/mach-mips
 load-$(CONFIG_MIPS_SEAD)       += 0xffffffff80100000
 
 #
index 4c7d763f21134f34f6a38c439208549cd7eb31ce..51d62bd5d900f93ad5408e71a3df031e027ea840 100644 (file)
@@ -6,4 +6,3 @@
 # Makefile for the Alchemy Semiconductor Db1x00 board.
 
 lib-y := init.o board_setup.o irqmap.o
-obj-$(CONFIG_WM97XX_COMODULE) += mirage_ts.o
diff --git a/arch/mips/au1000/db1x00/mirage_ts.c b/arch/mips/au1000/db1x00/mirage_ts.c
deleted file mode 100644 (file)
index 0942dcf..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * linux/arch/mips/au1000/db1x00/mirage_ts.c
- *
- * BRIEF MODULE DESCRIPTION
- *     Glue between Mirage board-specific touchscreen pieces
- *     and generic Wolfson Codec touchscreen support.
- *
- *     Based on pb1100_ts.c used in Hydrogen II.
- *
- * Copyright (c) 2003 Embedded Edge, LLC
- *             dan@embeddededge.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  SOFTWARE  IS PROVIDED          ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,          INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED          TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN         CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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/types.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/wait.h>
-
-#include <asm/segment.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#include <asm/au1000.h>
-
-/*
- *  Imported interface to Wolfson Codec driver.
- */
-extern void *wm97xx_ts_get_handle(int which);
-extern int wm97xx_ts_ready(void* ts_handle);
-extern void wm97xx_ts_set_cal(void* ts_handle, int xscale, int xtrans, int yscale, int ytrans);
-extern u16 wm97xx_ts_get_ac97(void* ts_handle, u8 reg);
-extern void wm97xx_ts_set_ac97(void* ts_handle, u8 reg, u16 val);
-extern int wm97xx_ts_read_data(void* ts_handle, long* x, long* y, long* pressure);
-extern void wm97xx_ts_send_data(void* ts_handle, long x, long y, long z);
-
-int wm97xx_comodule_present = 1;
-
-
-#define TS_NAME "mirage_ts"
-
-#define err(format, arg...) printk(KERN_ERR TS_NAME ": " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO TS_NAME ": " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING TS_NAME ": " format "\n" , ## arg)
-#define DPRINTK(format, arg...) printk("%s: " format "\n", __FUNCTION__ , ## arg)
-
-
-#define PEN_DOWN_IRQ   AU1000_GPIO_7
-
-static struct task_struct *ts_task = 0;
-static DECLARE_COMPLETION(ts_complete);
-static DECLARE_WAIT_QUEUE_HEAD(pendown_wait);
-
-#ifdef CONFIG_WM97XX_FIVEWIRETS
-static int release_pressure = 1;
-#else
-static int release_pressure = 50;
-#endif
-
-typedef struct {
-   long x;
-   long y;
-} DOWN_EVENT;
-
-#define SAMPLE_RATE    50      /* samples per second */
-#define PEN_DEBOUNCE   5       /* samples for settling - fn of SAMPLE_RATE */
-#define PEN_UP_TIMEOUT 10      /* in seconds */
-#define PEN_UP_SETTLE  5       /* samples per second */
-
-static struct {
-       int xscale;
-       int xtrans;
-       int yscale;
-       int ytrans;
-} mirage_ts_cal =
-{
-#if 0
-       .xscale   = 84,
-       .xtrans = -157,
-       .yscale   = 66,
-       .ytrans = -150,
-#else
-       .xscale   = 84,
-       .xtrans = -150,
-       .yscale   = 66,
-       .ytrans = -146,
-#endif
-};
-
-
-static void pendown_irq(int irqnr, void *devid, struct pt_regs *regs)
-{
-//DPRINTK("got one 0x%x", au_readl(SYS_PINSTATERD));
-       wake_up(&pendown_wait);
-}
-
-static int ts_thread(void *id)
-{
-       static int pen_was_down = 0;
-       static DOWN_EVENT pen_xy;
-       long x, y, z;
-       void *ts;       /* handle */
-       struct task_struct *tsk = current;
-       int timeout = HZ / SAMPLE_RATE;
-
-       ts_task = tsk;
-
-       daemonize();
-       tsk->tty = NULL;
-       tsk->policy = SCHED_FIFO;
-       tsk->rt_priority = 1;
-       strcpy(tsk->comm, "touchscreen");
-
-       /* only want to receive SIGKILL */
-       spin_lock_irq(&tsk->sigmask_lock);
-       siginitsetinv(&tsk->blocked, sigmask(SIGKILL));
-       recalc_sigpending(tsk);
-       spin_unlock_irq(&tsk->sigmask_lock);
-
-       /* get handle for codec */
-       ts = wm97xx_ts_get_handle(0);
-
-       /* proceed only after everybody is ready */
-       wait_event_timeout(pendown_wait, wm97xx_ts_ready(ts), HZ/4);
-
-       /* board-specific calibration */
-       wm97xx_ts_set_cal(ts,
-                       mirage_ts_cal.xscale,
-                       mirage_ts_cal.xtrans,
-                       mirage_ts_cal.yscale,
-                       mirage_ts_cal.ytrans);
-
-       /* route Wolfson pendown interrupts to our GPIO */
-       au_sync();
-       wm97xx_ts_set_ac97(ts, 0x4c, wm97xx_ts_get_ac97(ts, 0x4c) & ~0x0008);
-       au_sync();
-       wm97xx_ts_set_ac97(ts, 0x56, wm97xx_ts_get_ac97(ts, 0x56) & ~0x0008);
-       au_sync();
-       wm97xx_ts_set_ac97(ts, 0x52, wm97xx_ts_get_ac97(ts, 0x52) | 0x2008);
-       au_sync();
-
-       for (;;) {
-               interruptible_sleep_on_timeout(&pendown_wait, timeout);
-               disable_irq(PEN_DOWN_IRQ);
-               if (signal_pending(tsk)) {
-                       break;
-               }
-
-               /* read codec */
-               if (!wm97xx_ts_read_data(ts, &x, &y, &z))
-                       z = 0;  /* treat no-data and pen-up the same */
-
-               if (signal_pending(tsk)) {
-                       break;
-               }
-
-               if (z >= release_pressure) {
-                       y = ~y; /* top to bottom */
-                       if (pen_was_down > 1 /*&& pen_was_down < PEN_DEBOUNCE*/) {//THXXX
-                               /* bounce ? */
-                               x = pen_xy.x;
-                               y = pen_xy.y;
-                               --pen_was_down;
-                       } else if (pen_was_down <= 1) {
-                               pen_xy.x = x;
-                               pen_xy.y = y;
-                               if (pen_was_down)
-                                       wm97xx_ts_send_data(ts, x, y, z);
-                               pen_was_down = PEN_DEBOUNCE;
-                       }
-                       //wm97xx_ts_send_data(ts, x, y, z);
-                       timeout = HZ / SAMPLE_RATE;
-               } else {
-                       if (pen_was_down) {
-                               if (--pen_was_down)
-                                       z = release_pressure;
-                               else //THXXX
-                               wm97xx_ts_send_data(ts, pen_xy.x, pen_xy.y, z);
-                       }
-                       /* The pendown signal takes some time to settle after
-                        * reading the pen pressure so wait a little
-                        * before enabling the pen.
-                        */
-                       if (! pen_was_down) {
-//                             interruptible_sleep_on_timeout(&pendown_wait, HZ / PEN_UP_SETTLE);
-                               timeout = HZ * PEN_UP_TIMEOUT;
-                       }
-               }
-               enable_irq(PEN_DOWN_IRQ);
-       }
-       enable_irq(PEN_DOWN_IRQ);
-       ts_task = NULL;
-       complete(&ts_complete);
-       return 0;
-}
-
-static int __init ts_mirage_init(void)
-{
-       int ret;
-
-       /* pen down signal is connected to GPIO 7 */
-
-       ret = request_irq(PEN_DOWN_IRQ, pendown_irq, 0, "ts-pendown", NULL);
-       if (ret) {
-               err("unable to get pendown irq%d: [%d]", PEN_DOWN_IRQ, ret);
-               return ret;
-       }
-
-       lock_kernel();
-       ret = kernel_thread(ts_thread, NULL, CLONE_FS | CLONE_FILES);
-       if (ret < 0) {
-               unlock_kernel();
-               return ret;
-       }
-       unlock_kernel();
-
-       info("Mirage touchscreen IRQ initialized.");
-
-       return 0;
-}
-
-static void __exit ts_mirage_exit(void)
-{
-       if (ts_task) {
-               send_sig(SIGKILL, ts_task, 1);
-               wait_for_completion(&ts_complete);
-       }
-
-       free_irq(PEN_DOWN_IRQ, NULL);
-}
-
-module_init(ts_mirage_init);
-module_exit(ts_mirage_exit);
-
index bbb4ea43da88e37bf8fff9ded7397209a0996f29..cc1ce77eab4a7fd3757eeba3dc6dd8b1f8505c56 100644 (file)
@@ -68,7 +68,7 @@ enum {
 
 
 static struct resource
-       excite_ctr_resource = {
+       excite_ctr_resource __attribute__((unused)) = {
                .name           = "GPI counters",
                .start          = 0,
                .end            = 5,
@@ -77,7 +77,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_gpislice_resource = {
+       excite_gpislice_resource __attribute__((unused)) = {
                .name           = "GPI slices",
                .start          = 0,
                .end            = 1,
@@ -86,7 +86,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_mdio_channel_resource = {
+       excite_mdio_channel_resource __attribute__((unused)) = {
                .name           = "MDIO channels",
                .start          = 0,
                .end            = 1,
@@ -95,7 +95,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_fifomem_resource = {
+       excite_fifomem_resource __attribute__((unused)) = {
                .name           = "FIFO memory",
                .start          = 0,
                .end            = 767,
@@ -104,7 +104,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_scram_resource = {
+       excite_scram_resource __attribute__((unused)) = {
                .name           = "Scratch RAM",
                .start          = EXCITE_PHYS_SCRAM,
                .end            = EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1,
@@ -113,7 +113,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_fpga_resource = {
+       excite_fpga_resource __attribute__((unused)) = {
                .name           = "System FPGA",
                .start          = EXCITE_PHYS_FPGA,
                .end            = EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1,
@@ -122,7 +122,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_nand_resource = {
+       excite_nand_resource __attribute__((unused)) = {
                .name           = "NAND flash control",
                .start          = EXCITE_PHYS_NAND,
                .end            = EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1,
@@ -131,7 +131,7 @@ static struct resource
                .sibling        = NULL,
                .child          = NULL
        },
-       excite_titan_resource = {
+       excite_titan_resource __attribute__((unused)) = {
                .name           = "TITAN registers",
                .start          = EXCITE_PHYS_TITAN,
                .end            = EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1,
index 54274065e9a537e66e5d8dbe47bfc922cbfe5180..d3705284de39bf45d5c09dd34a1b7c7140168113 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1193,7 +1192,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 887fd959482a953d9be9ecdcc016430212010e0b..e12a475dcbf43cf85ef65bc5842837cda761ab2c 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index a01344f3a4c2c610f1533ae202ec110dfb2a31a7..bfade9abb767f7bf1c987806959f3240831113c1 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index c95682445a2802d7a1366ae9c4107683c341758f..4baf2ff1128a0ba8b24c3d854b113969402dceb0 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 CONFIG_MIPS_COBALT=y
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -828,7 +827,7 @@ CONFIG_FUSE_FS=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index c2f33d3af62c06a5d1c7d0caf92a0a5bfe7d209a..93cca1585bc342c08fb2ea2913c1698205379deb 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1000=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 8c44d16ae9a2b8f641ded987ab6bda67c6dba2ce..ffd99252a8376c9b83bd1cbc1797bf750ca5aa41 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1100=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index c13768e75ac5742c2ce556dd6ff00237b9d4b977..63eac5e89b9cdd63ae4208f8a261d4264a0d342d 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1200=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 8aea73fae7fb3b2220268cc06f1a59a409ad1bf4..25a095f7dc4ef56dcab70debf6a207ce333c1111 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1500=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 90ccb7359630fa7ebdac11d302555723a2f942e1..dda469c842b35dedff228dd521e1229d5daa2f0e 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_DB1550=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index b598cf08f15637dfcd3762e73368efb09e4d3c3c..fcd3dd19bc744e252440c318cdcc58edabfd9c3d 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 597150b140771b8cd34103c65d9a5de3db344c66..8683e0df12e07615aaff8425a1490aa070fa5c41 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 CONFIG_MACH_DECSTATION=y
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index fa2996bb4b7c8162a319f323b984a112fead3548..4ace61c95778992ad929c2d11a45b9b206655569 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:02 2006
+# Linux kernel version: 2.6.18-rc2
+# Tue Jul 25 23:15:03 2006
 #
 CONFIG_MIPS=y
 
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -227,7 +226,6 @@ CONFIG_MMU=y
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
 
 #
 # PCI Hotplug Support
@@ -254,7 +252,6 @@ CONFIG_TRAD_SIGNALS=y
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -284,6 +281,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 
@@ -643,6 +641,7 @@ CONFIG_MSDOS_PARTITION=y
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
@@ -650,7 +649,7 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="console=ttyVR0,19200 mem=8M"
+CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x1f0,0x3f6,40 mem=8M"
 
 #
 # Security options
index 375b2ac24a492c3732b72053eec97f554ca77b34..5847c916c130a90bf79b9e7f84f28be32ce809f7 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index b0afc118bd5c2498dc41f30a8b78d62278640b39..bc4c4f125c480087235a66bf41f2084b4ab11be2 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 CONFIG_MIPS_EV64120=y
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 045ebd0898935e02abfc002622b29226ef0579d6..eb87cbbfd03729923e9753d635268b28595a8057 100644 (file)
@@ -26,7 +26,6 @@ CONFIG_BASLER_EXCITE=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index ef16d1fb50715a5b45520d6eaad7afd8bc62ed8d..cc9b24eda9e89480f17b0ddfb09d506d86febdae 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1013,7 +1012,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 4bf1ee7f5f0033fc0471f7b4ac69d3b91aa624e2..50092ba8aa7135e381403a2459dbf74f88ee96c0 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -900,7 +899,7 @@ CONFIG_FUSE_FS=m
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index f83dc09c3ca99782ca4fd6fec3ac76fdfe13f5d5..dec2ba6ba03f428a2b72c0780d28ac9149e2255b 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index a91d72a9ca8687c940b22a7e25555d07b56fd5ec..37f9dd7187b1073d12ba0a0ffda7597cfc6372ea 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 CONFIG_MIPS_ITE8172=y
 # CONFIG_MACH_JAZZ is not set
index cebc67212d0621e536f74259791e3d113b2203e3..18874a4c24fec8978ea5539c29e36d81265026f6 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 CONFIG_MIPS_IVR=y
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 5d9eb11aba3d0d1a5f9209d7cab57d65246ec9d0..9f1e3048d62347417d464d32ec7cc9ef5fb8bea0 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -731,7 +730,7 @@ CONFIG_FUSE_FS=m
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
index be45a9044d06583ecd7b42b69544348de585a8f4..fded3f73815feaf13cfda7e025d6056a5949b803 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 64dc9f45a19c66e2f27dd15a8b40b40e2749bd60..320b8cdd6e589e9bfbac7127c53bdff629693a2a 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -905,7 +904,7 @@ CONFIG_FUSE_FS=m
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 2690baf15a857833777513dad397d3b7cdca0fc2..0ba1ef5048fb0a88a5cbf0c96619fb11cb0cab3d 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1230,7 +1229,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index c298979c18ae2be2eedab97c9d259be23b94bd24..adbeeadddb8f3da2bb16bd1270b4973793ef1cde 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 938b38ab5239ca9c32367695cfee543ae2db986c..79fd544fcb2a186b3ca0abcb5e8d4b319137a1cb 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:15 2006
+# Linux kernel version: 2.6.18-rc2
+# Tue Jul 25 23:16:46 2006
 #
 CONFIG_MIPS=y
 
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -71,7 +70,6 @@ CONFIG_MACH_VR41XX=y
 CONFIG_VICTOR_MPC30X=y
 # CONFIG_ZAO_CAPCELLA is not set
 CONFIG_PCI_VR41XX=y
-CONFIG_VRC4173=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
@@ -168,6 +166,7 @@ CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
@@ -841,7 +840,7 @@ CONFIG_USB_PEGASUS=m
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
-# CONFIG_USB_CY7C63 is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
 # CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
@@ -982,7 +981,6 @@ CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1007,6 +1005,7 @@ CONFIG_MSDOS_PARTITION=y
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
@@ -1014,7 +1013,7 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="mem=32M console=ttyVR0,19200"
+CONFIG_CMDLINE="mem=32M console=ttyVR0,19200 ide0=0x170,0x376,73"
 
 #
 # Security options
index ec5758f22676a98a6f9a11c85ac28eeee459e209..4d87da2b99fde8ee93cd2c14deff41256ce935bb 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 0d33d87de1a1834fe672864cba7729de097e9d7a..a7ac2b0a8273a87ad46222717021bb316e96a331 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -774,7 +773,7 @@ CONFIG_FUSE_FS=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 4b999102715eb761cc637991551c3907101db461..853e7bba5122e3294498a9224795b641c669370e 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -723,7 +722,7 @@ CONFIG_FUSE_FS=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 827b344f60100084b424537c3e6d519964f87f4c..8524efa23a490b7983c04d7149a6106728ca1109 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -777,7 +776,7 @@ CONFIG_FUSE_FS=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 9ed60fef69e024091e39ab5a0516b3924668e0ad..1a16e92900cbd9140f555f77a4f3d85eb791abb9 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_PB1100=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 6774254b1be660cbe351428e3ed4569b544e44a2..9ea8edea6f2934c03b553038e824a9d856ff5a0c 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_PB1500=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 1afe5bf6e765617fef2cdaab291d89201f5ba0ee..c4a158976f8f97209cc524b4ed14e23a322d249c 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS_PB1550=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index ac616c82d348c4bc4d3aa989a951e358ef7aee01..1cbf270c301ce416b8d84300db216980cb04e302 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index a8eb51bae3f36b6a1a922d3cffad4ea153a94534..bec30b15b9bdc448225cdee4ca981ca87da62362 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 6a63a113b7ea6a8ddc6d74711caaa82ef58d5ae9..f5f799e9370728d57f0f95dfc42c2f511e8c8b7b 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -687,7 +686,7 @@ CONFIG_FUSE_FS=y
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
index 6779f449bd2d8d5f45328dc3431745511b00826d..2f5650227ba36aefbd454184f95f0f09699e2c9c 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index b7826d3a2b77d0366d28c786dff02eb627df1f37..4fee90b2b100920580610e49900c19f4a1ecb774 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1442,7 +1441,7 @@ CONFIG_NTFS_FS=m
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
index 625c1c619b6be225f58932874f3b3990acf9b71c..9041f095f96fb892f7c0c04937040227c9e118b1 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 4401b602118f0e19a83725c1def2dfb6aade9455..02abb2f1bfaf017b63f4379ffd52c02a9ca2ce00 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 2ba4e25e8c34e8c7f63508af4ea3190ace23b035..ca3d0c4ba15b5861b4147bc08cd7af91b84cd291 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index fc8a407c1addad2de7e925ce0310f0639b533676..4e2009ace278d7ce076074a089400caae5e99600 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index effcb63b81a327edc78c83f46c0282c780c3ad0b..535a813d01a932ba20936f3a71fdb6ceeb96111d 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 4891d02ef8caba5a7f9ede6293dbfd9ce5a9ed9d..3a3ef20b21cc0afbe9c13d6b6b1c70282dfd9eb3 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:21 2006
+# Linux kernel version: 2.6.18-rc2
+# Tue Jul 25 23:13:04 2006
 #
 CONFIG_MIPS=y
 
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -166,6 +165,7 @@ CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
@@ -379,6 +379,7 @@ CONFIG_CONNECTOR=m
 CONFIG_BLK_DEV_RAM=m
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
@@ -855,7 +856,6 @@ CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
-# CONFIG_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -880,6 +880,7 @@ CONFIG_MSDOS_PARTITION=y
 #
 # Kernel hacking
 #
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 # CONFIG_PRINTK_TIME is not set
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_UNUSED_SYMBOLS is not set
@@ -887,7 +888,7 @@ CONFIG_MSDOS_PARTITION=y
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_FS is not set
 CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE="console=ttyVR0,19200 mem=16M"
+CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x170,0x376,49 mem=16M"
 
 #
 # Security options
index 3e4b16b39827b5961ed891f1efc1e58abfdf52bc..e6b1dea5584245b12be1b1d688667ea8e0bc22bf 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index 3a68d8a25b661fb6506d7aede28cf383ed9d2fa4..06a072b77b1c963a75a620da8fc6563c4eb6e1d8 100644 (file)
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
index fff6fcc96212e65b9f252d1c6790b4c2aeb3d3bb..cc9b24eda9e89480f17b0ddfb09d506d86febdae 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 09:49:33 2006
+# Thu Jul  6 10:04:10 2006
 #
 CONFIG_MIPS=y
 
@@ -25,7 +25,6 @@ CONFIG_MIPS=y
 # CONFIG_MIPS_COBALT is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MIPS_EV64120 is not set
-# CONFIG_MIPS_EV96100 is not set
 # CONFIG_MIPS_IVR is not set
 # CONFIG_MIPS_ITE8172 is not set
 # CONFIG_MACH_JAZZ is not set
@@ -1013,7 +1012,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 # CONFIG_CONFIGFS_FS is not set
diff --git a/arch/mips/galileo-boards/ev96100/Makefile b/arch/mips/galileo-boards/ev96100/Makefile
deleted file mode 100644 (file)
index cd868ec..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-#  Copyright 2000 MontaVista Software Inc.
-#  Author: MontaVista Software, Inc.
-#      ppopov@mvista.com or source@mvista.com
-#
-# Makefile for the Galileo EV96100 board.
-#
-
-obj-y          += init.o irq.o puts.o reset.o time.o setup.o
diff --git a/arch/mips/galileo-boards/ev96100/init.c b/arch/mips/galileo-boards/ev96100/init.c
deleted file mode 100644 (file)
index a01fe9b..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/generic/generic.c
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, 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 as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/bootmem.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/gt64120.h>
-
-
-/* Environment variable */
-
-typedef struct {
-       char *name;
-       char *val;
-} t_env_var;
-
-int prom_argc;
-char **prom_argv, **prom_envp;
-
-int init_debug = 0;
-
-char * __init prom_getcmdline(void)
-{
-       return &(arcs_cmdline[0]);
-}
-
-unsigned long __init prom_free_prom_memory(void)
-{
-       return 0;
-}
-
-void  __init prom_init_cmdline(void)
-{
-       char *cp;
-       int actr;
-
-       actr = 1; /* Always ignore argv[0] */
-
-       cp = &(arcs_cmdline[0]);
-       while(actr < prom_argc) {
-               strcpy(cp, prom_argv[actr]);
-               cp += strlen(prom_argv[actr]);
-               *cp++ = ' ';
-               actr++;
-       }
-       if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
-               --cp;
-       *cp = '\0';
-}
-
-char *prom_getenv(char *envname)
-{
-       /*
-        * Return a pointer to the given environment variable.
-        */
-
-       t_env_var *env = (t_env_var *) prom_envp;
-       int i;
-
-       i = strlen(envname);
-
-       while (env->name) {
-               if (strncmp(envname, env->name, i) == 0) {
-                       return (env->val);
-               }
-               env++;
-       }
-       return (NULL);
-}
-
-static inline unsigned char str2hexnum(unsigned char c)
-{
-       if (c >= '0' && c <= '9')
-               return c - '0';
-       if (c >= 'a' && c <= 'f')
-               return c - 'a' + 10;
-       return 0;               /* foo */
-}
-
-static inline void str2eaddr(unsigned char *ea, unsigned char *str)
-{
-       int i;
-
-       for (i = 0; i < 6; i++) {
-               unsigned char num;
-
-               if ((*str == '.') || (*str == ':'))
-                       str++;
-               num = str2hexnum(*str++) << 4;
-               num |= (str2hexnum(*str++));
-               ea[i] = num;
-       }
-}
-
-int get_ethernet_addr(char *ethernet_addr)
-{
-       char *ethaddr_str;
-
-       ethaddr_str = prom_getenv("ethaddr");
-       if (!ethaddr_str) {
-               printk("ethaddr not set in boot prom\n");
-               return -1;
-       }
-       str2eaddr(ethernet_addr, ethaddr_str);
-
-       if (init_debug > 1) {
-               int i;
-               printk("get_ethernet_addr: ");
-               for (i = 0; i < 5; i++)
-                       printk("%02x:",
-                              (unsigned char) *(ethernet_addr + i));
-               printk("%02x\n", *(ethernet_addr + i));
-       }
-
-       return 0;
-}
-
-const char *get_system_type(void)
-{
-       return "Galileo EV96100";
-}
-
-void __init prom_init(void)
-{
-       volatile unsigned char *uart;
-       char ppbuf[8];
-
-       prom_argc = fw_arg0;
-       prom_argv = (char **) fw_arg1;
-       prom_envp = (char **) fw_arg2;
-
-       mips_machgroup = MACH_GROUP_GALILEO;
-       mips_machtype = MACH_EV96100;
-
-       prom_init_cmdline();
-
-       /* 32 MB upgradable */
-       add_memory_region(0, 32 << 20, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/galileo-boards/ev96100/irq.c b/arch/mips/galileo-boards/ev96100/irq.c
deleted file mode 100644 (file)
index ee5d672..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/atlas/atlas_int.c.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, 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 as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <asm/irq_cpu.h>
-
-static inline unsigned int ffz8(unsigned int word)
-{
-       unsigned long k;
-
-       k = 7;
-       if (word & 0x0fUL) { k -= 4;  word <<= 4;  }
-       if (word & 0x30UL) { k -= 2;  word <<= 2;  }
-       if (word & 0x40UL) { k -= 1; }
-
-       return k;
-}
-
-extern void mips_timer_interrupt(struct pt_regs *regs);
-
-asmlinkage void ev96100_cpu_irq(unsigned int pending, struct pt_regs *regs)
-{
-       do_IRQ(ffz8(pending >> 8), regs);
-}
-
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
-{
-       unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
-
-       if (pending & CAUSEF_IP7)
-               mips_timer_interrupt(regs);
-       else if (pending)
-               ev96100_cpu_irq(pending, regs);
-       else
-               spurious_interrupt(regs);
-}
-
-void __init arch_init_irq(void)
-{
-       mips_cpu_irq_init(0);
-}
diff --git a/arch/mips/galileo-boards/ev96100/puts.c b/arch/mips/galileo-boards/ev96100/puts.c
deleted file mode 100644 (file)
index 49dc6d1..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-
-/*
- * Debug routines which directly access the uart.
- */
-
-#include <linux/types.h>
-#include <asm/gt64120.h>
-
-
-//#define SERIAL_BASE    EV96100_UART0_REGS_BASE
-#define SERIAL_BASE    0xBD000020
-#define NS16550_BASE   SERIAL_BASE
-
-#define SERA_CMD       0x0D
-#define SERA_DATA      0x08
-//#define SERB_CMD       0x05
-#define SERB_CMD       20
-#define SERB_DATA      0x00
-#define TX_BUSY        0x20
-
-#define TIMEOUT    0xffff
-#undef SLOW_DOWN
-
-static const char digits[16] = "0123456789abcdef";
-static volatile unsigned char *const com1 = (unsigned char *) SERIAL_BASE;
-
-
-#ifdef SLOW_DOWN
-static inline void slow_down()
-{
-       int k;
-       for (k = 0; k < 10000; k++);
-}
-#else
-#define slow_down()
-#endif
-
-void putch(const unsigned char c)
-{
-       unsigned char ch;
-       int i = 0;
-
-       do {
-               ch = com1[SERB_CMD];
-               slow_down();
-               i++;
-               if (i > TIMEOUT) {
-                       break;
-               }
-       } while (0 == (ch & TX_BUSY));
-       com1[SERB_DATA] = c;
-}
-
-void putchar(const unsigned char c)
-{
-       unsigned char ch;
-       int i = 0;
-
-       do {
-               ch = com1[SERB_CMD];
-               slow_down();
-               i++;
-               if (i > TIMEOUT) {
-                       break;
-               }
-       } while (0 == (ch & TX_BUSY));
-       com1[SERB_DATA] = c;
-}
-
-void puts(unsigned char *cp)
-{
-       unsigned char ch;
-       int i = 0;
-
-       while (*cp) {
-               do {
-                       ch = com1[SERB_CMD];
-                       slow_down();
-                       i++;
-                       if (i > TIMEOUT) {
-                               break;
-                       }
-               } while (0 == (ch & TX_BUSY));
-               com1[SERB_DATA] = *cp++;
-       }
-       putch('\r');
-       putch('\n');
-}
-
-void fputs(unsigned char *cp)
-{
-       unsigned char ch;
-       int i = 0;
-
-       while (*cp) {
-
-               do {
-                       ch = com1[SERB_CMD];
-                       slow_down();
-                       i++;
-                       if (i > TIMEOUT) {
-                               break;
-                       }
-               } while (0 == (ch & TX_BUSY));
-               com1[SERB_DATA] = *cp++;
-       }
-}
-
-
-void put64(uint64_t ul)
-{
-       int cnt;
-       unsigned ch;
-
-       cnt = 16;               /* 16 nibbles in a 64 bit long */
-       putch('0');
-       putch('x');
-       do {
-               cnt--;
-               ch = (unsigned char) (ul >> cnt * 4) & 0x0F;
-               putch(digits[ch]);
-       } while (cnt > 0);
-}
-
-void put32(unsigned u)
-{
-       int cnt;
-       unsigned ch;
-
-       cnt = 8;                /* 8 nibbles in a 32 bit long */
-       putch('0');
-       putch('x');
-       do {
-               cnt--;
-               ch = (unsigned char) (u >> cnt * 4) & 0x0F;
-               putch(digits[ch]);
-       } while (cnt > 0);
-}
diff --git a/arch/mips/galileo-boards/ev96100/reset.c b/arch/mips/galileo-boards/ev96100/reset.c
deleted file mode 100644 (file)
index 5ef9b7f..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Galileo EV96100 reset routines.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/generic/reset.c
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, 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 as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <asm/gt64120.h>
-
-static void mips_machine_restart(char *command);
-static void mips_machine_halt(void);
-
-static void mips_machine_restart(char *command)
-{
-       set_c0_status(ST0_BEV | ST0_ERL);
-       change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
-       flush_cache_all();
-       write_c0_wired(0);
-       __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
-       while (1);
-}
-
-static void mips_machine_halt(void)
-{
-       printk(KERN_NOTICE "You can safely turn off the power\n");
-       while (1)
-               __asm__(".set\tmips3\n\t"
-                       "wait\n\t"
-                       ".set\tmips0");
-}
-
-void mips_reboot_setup(void)
-{
-       _machine_restart = mips_machine_restart;
-       _machine_halt = mips_machine_halt;
-}
diff --git a/arch/mips/galileo-boards/ev96100/setup.c b/arch/mips/galileo-boards/ev96100/setup.c
deleted file mode 100644 (file)
index 639ad55..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Galileo EV96100 setup.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/atlas/atlas_setup.c.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, 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 as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
-#include <linux/pci.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/mipsregs.h>
-#include <asm/irq.h>
-#include <asm/delay.h>
-#include <asm/gt64120.h>
-#include <asm/galileo-boards/ev96100int.h>
-
-
-extern char *__init prom_getcmdline(void);
-
-extern void mips_reboot_setup(void);
-
-unsigned char mac_0_1[12];
-
-void __init plat_mem_setup(void)
-{
-       unsigned int config = read_c0_config();
-       unsigned int status = read_c0_status();
-       unsigned int info = read_c0_info();
-       u32 tmp;
-
-       char *argptr;
-
-       clear_c0_status(ST0_FR);
-
-       if (config & 0x8)
-               printk("Secondary cache is enabled\n");
-       else
-               printk("Secondary cache is disabled\n");
-
-       if (status & (1 << 27))
-               printk("User-mode cache ops enabled\n");
-       else
-               printk("User-mode cache ops disabled\n");
-
-       printk("CP0 info reg: %x\n", (unsigned) info);
-       if (info & (1 << 28))
-               printk("burst mode Scache RAMS\n");
-       else
-               printk("pipelined Scache RAMS\n");
-
-       if (info & 0x1)
-               printk("Atomic Enable is set\n");
-
-       argptr = prom_getcmdline();
-#ifdef CONFIG_SERIAL_CONSOLE
-       if (strstr(argptr, "console=") == NULL) {
-               argptr = prom_getcmdline();
-               strcat(argptr, " console=ttyS0,115200");
-       }
-#endif
-
-       mips_reboot_setup();
-
-       set_io_port_base(KSEG1);
-       ioport_resource.start = GT_PCI_IO_BASE;
-       ioport_resource.end = GT_PCI_IO_BASE + 0x01ffffff;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-       ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
-#endif
-
-
-       /*
-        * Setup GT controller master bit so we can do config cycles
-        */
-
-       /* Clear cause register bits */
-       GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
-                                    GT_INTRCAUSE_TARABORT0_BIT));
-       /* Setup address */
-       GT_WRITE(GT_PCI0_CFGADDR_OFS,
-                (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-                (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-                ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-                GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
-       udelay(2);
-       tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
-
-       tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-               PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
-       GT_WRITE(GT_PCI0_CFGADDR_OFS,
-                (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-                (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-                ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-                GT_PCI0_CFGADDR_CONFIGEN_BIT);
-       udelay(2);
-       GT_WRITE(GT_PCI0_CFGDATA_OFS, tmp);
-
-       /* Setup address */
-       GT_WRITE(GT_PCI0_CFGADDR_OFS,
-                (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-                (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-                ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-                GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
-       udelay(2);
-       tmp = GT_READ(GT_PCI0_CFGDATA_OFS);
-}
-
-unsigned short get_gt_devid(void)
-{
-       u32 gt_devid;
-
-       /* Figure out if this is a gt96100 or gt96100A */
-       GT_WRITE(GT_PCI0_CFGADDR_OFS,
-                (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-                (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-                ((PCI_VENDOR_ID / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-                GT_PCI0_CFGADDR_CONFIGEN_BIT);
-
-       udelay(4);
-       gt_devid = GT_READ(GT_PCI0_CFGDATA_OFS);
-
-       return gt_devid >> 16;
-}
diff --git a/arch/mips/galileo-boards/ev96100/time.c b/arch/mips/galileo-boards/ev96100/time.c
deleted file mode 100644 (file)
index 8cbe842..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Galileo EV96100 rtc routines.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/atlas/atlas_rtc.c.
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, 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 as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/timex.h>
-
-#include <asm/mipsregs.h>
-#include <asm/ptrace.h>
-#include <asm/time.h>
-
-
-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
-
-extern volatile unsigned long wall_jiffies;
-unsigned long missed_heart_beats = 0;
-
-static unsigned long r4k_offset; /* Amount to increment compare reg each time */
-static unsigned long r4k_cur;    /* What counter should be at next timer irq */
-
-static inline void ack_r4ktimer(unsigned long newval)
-{
-       write_c0_compare(newval);
-}
-
-/*
- * There are a lot of conceptually broken versions of the MIPS timer interrupt
- * handler floating around.  This one is rather different, but the algorithm
- * is probably more robust.
- */
-void mips_timer_interrupt(struct pt_regs *regs)
-{
-        int irq = 7; /* FIX ME */
-
-       if (r4k_offset == 0) {
-            goto null;
-        }
-
-       do {
-               kstat_this_cpu.irqs[irq]++;
-               do_timer(regs);
-#ifndef CONFIG_SMP
-               update_process_times(user_mode(regs));
-#endif
-               r4k_cur += r4k_offset;
-               ack_r4ktimer(r4k_cur);
-
-       } while (((unsigned long)read_c0_count()
-                    - r4k_cur) < 0x7fffffff);
-       return;
-
-null:
-       ack_r4ktimer(0);
-}
index aa2caa67299a45ec4b5d8950b82bf695d611855c..9fbf8430c8499972ab80047026c803e64306a253 100644 (file)
@@ -38,15 +38,40 @@ static void r3081_wait(void)
 
 static void r39xx_wait(void)
 {
-       unsigned long cfg = read_c0_conf();
-       write_c0_conf(cfg | TX39_CONF_HALT);
+       local_irq_disable();
+       if (!need_resched())
+               write_c0_conf(read_c0_conf() | TX39_CONF_HALT);
+       local_irq_enable();
 }
 
+/*
+ * There is a race when WAIT instruction executed with interrupt
+ * enabled.
+ * But it is implementation-dependent wheter the pipelie restarts when
+ * a non-enabled interrupt is requested.
+ */
 static void r4k_wait(void)
 {
-       __asm__(".set\tmips3\n\t"
-               "wait\n\t"
-               ".set\tmips0");
+       __asm__("       .set    mips3                   \n"
+               "       wait                            \n"
+               "       .set    mips0                   \n");
+}
+
+/*
+ * This variant is preferable as it allows testing need_resched and going to
+ * sleep depending on the outcome atomically.  Unfortunately the "It is
+ * implementation-dependent whether the pipeline restarts when a non-enabled
+ * interrupt is requested" restriction in the MIPS32/MIPS64 architecture makes
+ * using this version a gamble.
+ */
+static void r4k_wait_irqoff(void)
+{
+       local_irq_disable();
+       if (!need_resched())
+               __asm__("       .set    mips3           \n"
+                       "       wait                    \n"
+                       "       .set    mips0           \n");
+       local_irq_enable();
 }
 
 /* The Au1xxx wait is available only if using 32khz counter or
@@ -56,17 +81,17 @@ int allow_au1k_wait;
 static void au1k_wait(void)
 {
        /* using the wait instruction makes CP0 counter unusable */
-       __asm__(".set mips3\n\t"
-               "cache 0x14, 0(%0)\n\t"
-               "cache 0x14, 32(%0)\n\t"
-               "sync\n\t"
-               "nop\n\t"
-               "wait\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               "nop\n\t"
-               ".set mips0\n\t"
+       __asm__("       .set    mips3                   \n"
+               "       cache   0x14, 0(%0)             \n"
+               "       cache   0x14, 32(%0)            \n"
+               "       sync                            \n"
+               "       nop                             \n"
+               "       wait                            \n"
+               "       nop                             \n"
+               "       nop                             \n"
+               "       nop                             \n"
+               "       nop                             \n"
+               "       .set    mips0                   \n"
                : : "r" (au1k_wait));
 }
 
@@ -111,7 +136,6 @@ static inline void check_wait(void)
        case CPU_NEVADA:
        case CPU_RM7000:
        case CPU_RM9000:
-       case CPU_TX49XX:
        case CPU_4KC:
        case CPU_4KEC:
        case CPU_4KSC:
@@ -125,6 +149,10 @@ static inline void check_wait(void)
                cpu_wait = r4k_wait;
                printk(" available.\n");
                break;
+       case CPU_TX49XX:
+               cpu_wait = r4k_wait_irqoff;
+               printk(" available.\n");
+               break;
        case CPU_AU1000:
        case CPU_AU1100:
        case CPU_AU1500:
index 676e868d26fb15ab79b23d7c69be792276185be8..2132485caa744bbeddca7b4af11070b2e8c8591f 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/uaccess.h>
+#include <asm/unistd.h>
 
 #undef DEBUG_SIG
 
@@ -172,11 +173,12 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
        return ret;
 }
 
-asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
+void do_irix_signal(struct pt_regs *regs)
 {
        struct k_sigaction ka;
        siginfo_t info;
        int signr;
+       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which is why we may in certain
@@ -184,19 +186,28 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
         * if so.
         */
        if (!user_mode(regs))
-               return 1;
+               return;
 
-       if (try_to_freeze())
-               goto no_signal;
-
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-       if (signr > 0)
-               return handle_signal(signr, &info, &ka, oldset, regs);
+       if (signr > 0) {
+               /* Whee!  Actually deliver the signal.  */
+               if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+                       /* a signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TIF_RESTORE_SIGMASK flag */
+                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               }
+
+               return;
+       }
 
-no_signal:
        /*
         * Who's code doesn't conform to the restartable syscall convention
         * dies here!!!  The li instruction, a single machine instruction,
@@ -208,8 +219,22 @@ no_signal:
                    regs->regs[2] == ERESTARTNOINTR) {
                        regs->cp0_epc -= 8;
                }
+               if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
+                       regs->regs[2] = __NR_restart_syscall;
+                       regs->regs[7] = regs->regs[26];
+                       regs->cp0_epc -= 4;
+               }
+               regs->regs[0] = 0;      /* Don't deal with this again.  */
+       }
+
+       /*
+       * If there's no signal to deliver, we just put the saved sigmask
+       * back
+       */
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
-       return 0;
 }
 
 asmlinkage void
@@ -298,6 +323,9 @@ struct sigact_irix5 {
        int _unused0[2];
 };
 
+#define SIG_SETMASK32  256     /* Goodie from SGI for BSD compatibility:
+                                  set only the low 32 bit of the sigset.  */
+
 #ifdef DEBUG_SIG
 static inline void dump_sigact_irix5(struct sigact_irix5 *p)
 {
@@ -413,7 +441,7 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new,
 
 asmlinkage int irix_sigsuspend(struct pt_regs *regs)
 {
-       sigset_t saveset, newset;
+       sigset_t newset;
        sigset_t __user *uset;
 
        uset = (sigset_t __user *) regs->regs[4];
@@ -422,18 +450,15 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs)
        sigdelsetmask(&newset, ~_BLOCKABLE);
 
        spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
+       current->saved_sigmask = current->blocked;
        current->blocked = newset;
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       regs->regs[2] = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_irix_signal(&saveset, regs))
-                       return -EINTR;
-       }
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_thread_flag(TIF_RESTORE_SIGMASK);
+       return -ERESTARTNOHAND;
 }
 
 /* hate hate hate... */
index 450ac592da576c8314a1cec7d0851d891e4cc1d7..43b1162d714f281db07a3bad5b53bcf0576f8423 100644 (file)
@@ -991,7 +991,7 @@ struct sysctl_args32
        unsigned int __unused[4];
 };
 
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
 
 asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
 {
@@ -1032,7 +1032,7 @@ asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
        return error;
 }
 
-#endif /* CONFIG_SYSCTL */
+#endif /* CONFIG_SYSCTL_SYSCALL */
 
 asmlinkage long sys32_newuname(struct new_utsname __user * name)
 {
@@ -1296,9 +1296,3 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs)
        return do_fork(clone_flags, newsp, &regs, 0,
                       parent_tidptr, child_tidptr);
 }
-
-extern asmlinkage void sys_set_thread_area(u32 addr);
-asmlinkage void sys32_set_thread_area(u32 addr)
-{
-       sys_set_thread_area(AA(addr));
-}
index 7ab67f786bfe277327f55517364855f4fc728b2f..2613a0dd4b823bde6959cd575d194cb8cb5677b8 100644 (file)
@@ -273,104 +273,107 @@ long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
        return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
 
-static struct mips_frame_info {
-       void *func;
-       unsigned long func_size;
-       int frame_size;
-       int pc_offset;
-} *schedule_frame, mfinfo[64];
-static int mfinfo_num;
-
-static int __init get_frame_info(struct mips_frame_info *info)
+/*
+ *
+ */
+struct mips_frame_info {
+       void            *func;
+       unsigned long   func_size;
+       int             frame_size;
+       int             pc_offset;
+};
+
+static inline int is_ra_save_ins(union mips_instruction *ip)
 {
-       int i;
-       void *func = info->func;
-       union mips_instruction *ip = (union mips_instruction *)func;
+       /* sw / sd $ra, offset($sp) */
+       return (ip->i_format.opcode == sw_op || ip->i_format.opcode == sd_op) &&
+               ip->i_format.rs == 29 &&
+               ip->i_format.rt == 31;
+}
+
+static inline int is_jal_jalr_jr_ins(union mips_instruction *ip)
+{
+       if (ip->j_format.opcode == jal_op)
+               return 1;
+       if (ip->r_format.opcode != spec_op)
+               return 0;
+       return ip->r_format.func == jalr_op || ip->r_format.func == jr_op;
+}
+
+static inline int is_sp_move_ins(union mips_instruction *ip)
+{
+       /* addiu/daddiu sp,sp,-imm */
+       if (ip->i_format.rs != 29 || ip->i_format.rt != 29)
+               return 0;
+       if (ip->i_format.opcode == addiu_op || ip->i_format.opcode == daddiu_op)
+               return 1;
+       return 0;
+}
+
+static int get_frame_info(struct mips_frame_info *info)
+{
+       union mips_instruction *ip = info->func;
+       unsigned max_insns = info->func_size / sizeof(union mips_instruction);
+       unsigned i;
+
        info->pc_offset = -1;
        info->frame_size = 0;
-       for (i = 0; i < 128; i++, ip++) {
-               /* if jal, jalr, jr, stop. */
-               if (ip->j_format.opcode == jal_op ||
-                   (ip->r_format.opcode == spec_op &&
-                    (ip->r_format.func == jalr_op ||
-                     ip->r_format.func == jr_op)))
-                       break;
 
-               if (info->func_size && i >= info->func_size / 4)
+       if (!ip)
+               goto err;
+
+       if (max_insns == 0)
+               max_insns = 128U;       /* unknown function size */
+       max_insns = min(128U, max_insns);
+
+       for (i = 0; i < max_insns; i++, ip++) {
+
+               if (is_jal_jalr_jr_ins(ip))
                        break;
-               if (
-#ifdef CONFIG_32BIT
-                   ip->i_format.opcode == addiu_op &&
-#endif
-#ifdef CONFIG_64BIT
-                   ip->i_format.opcode == daddiu_op &&
-#endif
-                   ip->i_format.rs == 29 &&
-                   ip->i_format.rt == 29) {
-                       /* addiu/daddiu sp,sp,-imm */
-                       if (info->frame_size)
-                               continue;
-                       info->frame_size = - ip->i_format.simmediate;
+               if (!info->frame_size) {
+                       if (is_sp_move_ins(ip))
+                               info->frame_size = - ip->i_format.simmediate;
+                       continue;
                }
-
-               if (
-#ifdef CONFIG_32BIT
-                   ip->i_format.opcode == sw_op &&
-#endif
-#ifdef CONFIG_64BIT
-                   ip->i_format.opcode == sd_op &&
-#endif
-                   ip->i_format.rs == 29 &&
-                   ip->i_format.rt == 31) {
-                       /* sw / sd $ra, offset($sp) */
-                       if (info->pc_offset != -1)
-                               continue;
+               if (info->pc_offset == -1 && is_ra_save_ins(ip)) {
                        info->pc_offset =
                                ip->i_format.simmediate / sizeof(long);
+                       break;
                }
        }
-       if (info->pc_offset == -1 || info->frame_size == 0) {
-               if (func == schedule)
-                       printk("Can't analyze prologue code at %p\n", func);
-               info->pc_offset = -1;
-               info->frame_size = 0;
-       }
-
-       return 0;
+       if (info->frame_size && info->pc_offset >= 0) /* nested */
+               return 0;
+       if (info->pc_offset < 0) /* leaf */
+               return 1;
+       /* prologue seems boggus... */
+err:
+       return -1;
 }
 
+static struct mips_frame_info schedule_mfi __read_mostly;
+
 static int __init frame_info_init(void)
 {
-       int i;
+       unsigned long size = 0;
 #ifdef CONFIG_KALLSYMS
+       unsigned long ofs;
        char *modname;
        char namebuf[KSYM_NAME_LEN + 1];
-       unsigned long start, size, ofs;
-       extern char __sched_text_start[], __sched_text_end[];
-       extern char __lock_text_start[], __lock_text_end[];
-
-       start = (unsigned long)__sched_text_start;
-       for (i = 0; i < ARRAY_SIZE(mfinfo); i++) {
-               if (start == (unsigned long)schedule)
-                       schedule_frame = &mfinfo[i];
-               if (!kallsyms_lookup(start, &size, &ofs, &modname, namebuf))
-                       break;
-               mfinfo[i].func = (void *)(start + ofs);
-               mfinfo[i].func_size = size;
-               start += size - ofs;
-               if (start >= (unsigned long)__lock_text_end)
-                       break;
-               if (start == (unsigned long)__sched_text_end)
-                       start = (unsigned long)__lock_text_start;
-       }
-#else
-       mfinfo[0].func = schedule;
-       schedule_frame = &mfinfo[0];
+
+       kallsyms_lookup((unsigned long)schedule, &size, &ofs, &modname, namebuf);
 #endif
-       for (i = 0; i < ARRAY_SIZE(mfinfo) && mfinfo[i].func; i++)
-               get_frame_info(&mfinfo[i]);
+       schedule_mfi.func = schedule;
+       schedule_mfi.func_size = size;
+
+       get_frame_info(&schedule_mfi);
+
+       /*
+        * Without schedule() frame info, result given by
+        * thread_saved_pc() and get_wchan() are not reliable.
+        */
+       if (schedule_mfi.pc_offset < 0)
+               printk("Can't analyze schedule() prologue at %p\n", schedule);
 
-       mfinfo_num = i;
        return 0;
 }
 
@@ -386,54 +389,86 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
        /* New born processes are a special case */
        if (t->reg31 == (unsigned long) ret_from_fork)
                return t->reg31;
-
-       if (!schedule_frame || schedule_frame->pc_offset < 0)
+       if (schedule_mfi.pc_offset < 0)
                return 0;
-       return ((unsigned long *)t->reg29)[schedule_frame->pc_offset];
+       return ((unsigned long *)t->reg29)[schedule_mfi.pc_offset];
 }
 
-/* get_wchan - a maintenance nightmare^W^Wpain in the ass ...  */
-unsigned long get_wchan(struct task_struct *p)
+
+#ifdef CONFIG_KALLSYMS
+/* used by show_backtrace() */
+unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
+                          unsigned long pc, unsigned long ra)
 {
        unsigned long stack_page;
-       unsigned long pc;
-#ifdef CONFIG_KALLSYMS
-       unsigned long frame;
-#endif
+       struct mips_frame_info info;
+       char *modname;
+       char namebuf[KSYM_NAME_LEN + 1];
+       unsigned long size, ofs;
+       int leaf;
 
-       if (!p || p == current || p->state == TASK_RUNNING)
+       stack_page = (unsigned long)task_stack_page(task);
+       if (!stack_page)
                return 0;
 
-       stack_page = (unsigned long)task_stack_page(p);
-       if (!stack_page || !mfinfo_num)
+       if (!kallsyms_lookup(pc, &size, &ofs, &modname, namebuf))
+               return 0;
+       /*
+        * Return ra if an exception occured at the first instruction
+        */
+       if (unlikely(ofs == 0))
+               return ra;
+
+       info.func = (void *)(pc - ofs);
+       info.func_size = ofs;   /* analyze from start to ofs */
+       leaf = get_frame_info(&info);
+       if (leaf < 0)
+               return 0;
+
+       if (*sp < stack_page ||
+           *sp + info.frame_size > stack_page + THREAD_SIZE - 32)
                return 0;
 
-       pc = thread_saved_pc(p);
+       if (leaf)
+               /*
+                * For some extreme cases, get_frame_info() can
+                * consider wrongly a nested function as a leaf
+                * one. In that cases avoid to return always the
+                * same value.
+                */
+               pc = pc != ra ? ra : 0;
+       else
+               pc = ((unsigned long *)(*sp))[info.pc_offset];
+
+       *sp += info.frame_size;
+       return __kernel_text_address(pc) ? pc : 0;
+}
+#endif
+
+/*
+ * get_wchan - a maintenance nightmare^W^Wpain in the ass ...
+ */
+unsigned long get_wchan(struct task_struct *task)
+{
+       unsigned long pc = 0;
 #ifdef CONFIG_KALLSYMS
-       if (!in_sched_functions(pc))
-               return pc;
+       unsigned long sp;
+#endif
 
-       frame = p->thread.reg29 + schedule_frame->frame_size;
-       do {
-               int i;
+       if (!task || task == current || task->state == TASK_RUNNING)
+               goto out;
+       if (!task_stack_page(task))
+               goto out;
 
-               if (frame < stack_page || frame > stack_page + THREAD_SIZE - 32)
-                       return 0;
+       pc = thread_saved_pc(task);
 
-               for (i = mfinfo_num - 1; i >= 0; i--) {
-                       if (pc >= (unsigned long) mfinfo[i].func)
-                               break;
-               }
-               if (i < 0)
-                       break;
+#ifdef CONFIG_KALLSYMS
+       sp = task->thread.reg29 + schedule_mfi.frame_size;
 
-               pc = ((unsigned long *)frame)[mfinfo[i].pc_offset];
-               if (!mfinfo[i].frame_size)
-                       break;
-               frame += mfinfo[i].frame_size;
-       } while (in_sched_functions(pc));
+       while (in_sched_functions(pc))
+               pc = unwind_stack(task, &sp, pc, 0);
 #endif
 
+out:
        return pc;
 }
-
index ba1bcd83c7d3ef71587a27d272f1fa970fdfef03..e7178510220635c5da2be58e59c3b839a36a0bfa 100644 (file)
@@ -662,6 +662,8 @@ einval:     li      v0, -EINVAL
        sys     sys_tee                 4
        sys     sys_vmsplice            4
        sys     sys_move_pages          6
+       sys     sys_set_robust_list     2
+       sys     sys_get_robust_list     3
        .endm
 
        /* We pre-compute the number of _instruction_ bytes needed to
index 939e172db9531451c8e82df36914ba7b532ab5e2..4c22d0b4825dc70bcdfb5d239dc458d60d6c185c 100644 (file)
@@ -466,3 +466,5 @@ sys_call_table:
        PTR     sys_tee                         /* 5265 */
        PTR     sys_vmsplice
        PTR     sys_move_pages
+       PTR     sys_set_robust_list
+       PTR     sys_get_robust_list
index 98abbc5a9f13007d5d6f034d5fd7d0c231c5f314..f25c2a2f10387b10128bd92251cc9ee8df45559f 100644 (file)
@@ -247,7 +247,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_capset
        PTR     sys32_rt_sigpending             /* 6125 */
        PTR     compat_sys_rt_sigtimedwait
-       PTR     sys_rt_sigqueueinfo
+       PTR     sys32_rt_sigqueueinfo
        PTR     sysn32_rt_sigsuspend
        PTR     sys32_sigaltstack
        PTR     compat_sys_utime                /* 6130 */
@@ -390,5 +390,7 @@ EXPORT(sysn32_call_table)
        PTR     sys_splice
        PTR     sys_sync_file_range
        PTR     sys_tee
-       PTR     sys_vmsplice                    /* 6271 */
+       PTR     sys_vmsplice                    /* 6270 */
        PTR     sys_move_pages
+       PTR     compat_sys_set_robust_list
+       PTR     compat_sys_get_robust_list
index 505c9ee540095f119b303cfcbc46e9ef86e74eca..288ee4ac4dbb8cce221c6b530b3da04bdae4eea1 100644 (file)
@@ -498,7 +498,7 @@ sys_call_table:
        PTR     sys_mknodat                     /* 4290 */
        PTR     sys_fchownat
        PTR     compat_sys_futimesat
-       PTR     compat_sys_newfstatat
+       PTR     sys_newfstatat
        PTR     sys_unlinkat
        PTR     sys_renameat                    /* 4295 */
        PTR     sys_linkat
@@ -514,4 +514,6 @@ sys_call_table:
        PTR     sys_tee
        PTR     sys_vmsplice
        PTR     compat_sys_move_pages
+       PTR     compat_sys_set_robust_list
+       PTR     compat_sys_get_robust_list      /* 4310 */
        .size   sys_call_table,.-sys_call_table
index 8c2b596a136f95376c45386b3fba0703d32f4991..fdbb508661c5d111af10dc3bce6d8d815fed681c 100644 (file)
  * Copyright (C) 1999 Silicon Graphics, Inc.
  * Copyright (C) 2000 2001, 2002  Maciej W. Rozycki
  */
-#include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
 #include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/string.h>
-#include <linux/unistd.h>
-#include <linux/slab.h>
-#include <linux/user.h>
-#include <linux/utsname.h>
-#include <linux/a.out.h>
 #include <linux/screen_info.h>
 #include <linux/bootmem.h>
 #include <linux/initrd.h>
-#include <linux/major.h>
-#include <linux/kdev_t.h>
 #include <linux/root_dev.h>
 #include <linux/highmem.h>
 #include <linux/console.h>
-#include <linux/mmzone.h>
 #include <linux/pfn.h>
 
 #include <asm/addrspace.h>
@@ -96,6 +82,12 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
        int x = boot_mem_map.nr_map;
        struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1;
 
+       /* Sanity check */
+       if (start + size < start) {
+               printk("Trying to add an invalid memory region, skipped\n");
+               return;
+       }
+
        /*
         * Try to merge with previous entry if any.  This is far less than
         * perfect but is sufficient for most real world cases.
@@ -143,167 +135,132 @@ static void __init print_memory_map(void)
        }
 }
 
-static inline void parse_cmdline_early(void)
+/*
+ * Manage initrd
+ */
+#ifdef CONFIG_BLK_DEV_INITRD
+
+static int __init rd_start_early(char *p)
 {
-       char c = ' ', *to = command_line, *from = saved_command_line;
-       unsigned long start_at, mem_size;
-       int len = 0;
-       int usermem = 0;
+       unsigned long start = memparse(p, &p);
 
-       printk("Determined physical RAM map:\n");
-       print_memory_map();
+#ifdef CONFIG_64BIT
+       /* HACK: Guess if the sign extension was forgotten */
+       if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
+               start |= 0xffffffff00000000UL;
+#endif
+       initrd_start = start;
+       initrd_end += start;
 
-       for (;;) {
-               /*
-                * "mem=XXX[kKmM]" defines a memory region from
-                * 0 to <XXX>, overriding the determined size.
-                * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from
-                * <YYY> to <YYY>+<XXX>, overriding the determined size.
-                */
-               if (c == ' ' && !memcmp(from, "mem=", 4)) {
-                       if (to != command_line)
-                               to--;
-                       /*
-                        * If a user specifies memory size, we
-                        * blow away any automatically generated
-                        * size.
-                        */
-                       if (usermem == 0) {
-                               boot_mem_map.nr_map = 0;
-                               usermem = 1;
-                       }
-                       mem_size = memparse(from + 4, &from);
-                       if (*from == '@')
-                               start_at = memparse(from + 1, &from);
-                       else
-                               start_at = 0;
-                       add_memory_region(start_at, mem_size, BOOT_MEM_RAM);
-               }
-               c = *(from++);
-               if (!c)
-                       break;
-               if (CL_SIZE <= ++len)
-                       break;
-               *(to++) = c;
-       }
-       *to = '\0';
+       return 0;
+}
+early_param("rd_start", rd_start_early);
 
-       if (usermem) {
-               printk("User-defined physical RAM map:\n");
-               print_memory_map();
-       }
+static int __init rd_size_early(char *p)
+{
+       initrd_end += memparse(p, &p);
+
+       return 0;
 }
+early_param("rd_size", rd_size_early);
 
-static inline int parse_rd_cmdline(unsigned long* rd_start, unsigned long* rd_end)
+static unsigned long __init init_initrd(void)
 {
+       unsigned long tmp, end, size;
+       u32 *initrd_header;
+
+       ROOT_DEV = Root_RAM0;
+
        /*
-        * "rd_start=0xNNNNNNNN" defines the memory address of an initrd
-        * "rd_size=0xNN" it's size
+        * Board specific code or command line parser should have
+        * already set up initrd_start and initrd_end. In these cases
+        * perfom sanity checks and use them if all looks good.
         */
-       unsigned long start = 0;
-       unsigned long size = 0;
-       unsigned long end;
-       char cmd_line[CL_SIZE];
-       char *start_str;
-       char *size_str;
-       char *tmp;
-
-       strcpy(cmd_line, command_line);
-       *command_line = 0;
-       tmp = cmd_line;
-       /* Ignore "rd_start=" strings in other parameters. */
-       start_str = strstr(cmd_line, "rd_start=");
-       if (start_str && start_str != cmd_line && *(start_str - 1) != ' ')
-               start_str = strstr(start_str, " rd_start=");
-       while (start_str) {
-               if (start_str != cmd_line)
-                       strncat(command_line, tmp, start_str - tmp);
-               start = memparse(start_str + 9, &start_str);
-               tmp = start_str + 1;
-               start_str = strstr(start_str, " rd_start=");
+       size = initrd_end - initrd_start;
+       if (initrd_end == 0 || size == 0) {
+               initrd_start = 0;
+               initrd_end = 0;
+       } else
+               return initrd_end;
+
+       end = (unsigned long)&_end;
+       tmp = PAGE_ALIGN(end) - sizeof(u32) * 2;
+       if (tmp < end)
+               tmp += PAGE_SIZE;
+
+       initrd_header = (u32 *)tmp;
+       if (initrd_header[0] == 0x494E5244) {
+               initrd_start = (unsigned long)&initrd_header[2];
+               initrd_end = initrd_start + initrd_header[1];
        }
-       if (*tmp)
-               strcat(command_line, tmp);
-
-       strcpy(cmd_line, command_line);
-       *command_line = 0;
-       tmp = cmd_line;
-       /* Ignore "rd_size" strings in other parameters. */
-       size_str = strstr(cmd_line, "rd_size=");
-       if (size_str && size_str != cmd_line && *(size_str - 1) != ' ')
-               size_str = strstr(size_str, " rd_size=");
-       while (size_str) {
-               if (size_str != cmd_line)
-                       strncat(command_line, tmp, size_str - tmp);
-               size = memparse(size_str + 8, &size_str);
-               tmp = size_str + 1;
-               size_str = strstr(size_str, " rd_size=");
+       return initrd_end;
+}
+
+static void __init finalize_initrd(void)
+{
+       unsigned long size = initrd_end - initrd_start;
+
+       if (size == 0) {
+               printk(KERN_INFO "Initrd not found or empty");
+               goto disable;
+       }
+       if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
+               printk("Initrd extends beyond end of memory");
+               goto disable;
        }
-       if (*tmp)
-               strcat(command_line, tmp);
 
-#ifdef CONFIG_64BIT
-       /* HACK: Guess if the sign extension was forgotten */
-       if (start > 0x0000000080000000 && start < 0x00000000ffffffff)
-               start |= 0xffffffff00000000UL;
+       reserve_bootmem(CPHYSADDR(initrd_start), size);
+       initrd_below_start_ok = 1;
+
+       printk(KERN_INFO "Initial ramdisk at: 0x%lx (%lu bytes)\n",
+              initrd_start, size);
+       return;
+disable:
+       printk(" - disabling initrd\n");
+       initrd_start = 0;
+       initrd_end = 0;
+}
+
+#else  /* !CONFIG_BLK_DEV_INITRD */
+
+#define init_initrd()          0
+#define finalize_initrd()      do {} while (0)
+
 #endif
 
-       end = start + size;
-       if (start && end) {
-               *rd_start = start;
-               *rd_end = end;
-               return 1;
-       }
-       return 0;
+/*
+ * Initialize the bootmem allocator. It also setup initrd related data
+ * if needed.
+ */
+#ifdef CONFIG_SGI_IP27
+
+static void __init bootmem_init(void)
+{
+       init_initrd();
+       finalize_initrd();
 }
 
-#define MAXMEM         HIGHMEM_START
-#define MAXMEM_PFN     PFN_DOWN(MAXMEM)
+#else  /* !CONFIG_SGI_IP27 */
 
-static inline void bootmem_init(void)
+static void __init bootmem_init(void)
 {
-       unsigned long start_pfn;
-       unsigned long reserved_end = (unsigned long)&_end;
-#ifndef CONFIG_SGI_IP27
-       unsigned long first_usable_pfn;
+       unsigned long reserved_end;
+       unsigned long highest = 0;
+       unsigned long mapstart = -1UL;
        unsigned long bootmap_size;
        int i;
-#endif
-#ifdef CONFIG_BLK_DEV_INITRD
-       int initrd_reserve_bootmem = 0;
-
-       /* Board specific code should have set up initrd_start and initrd_end */
-       ROOT_DEV = Root_RAM0;
-       if (parse_rd_cmdline(&initrd_start, &initrd_end)) {
-               reserved_end = max(reserved_end, initrd_end);
-               initrd_reserve_bootmem = 1;
-       } else {
-               unsigned long tmp;
-               u32 *initrd_header;
-
-               tmp = ((reserved_end + PAGE_SIZE-1) & PAGE_MASK) - sizeof(u32) * 2;
-               if (tmp < reserved_end)
-                       tmp += PAGE_SIZE;
-               initrd_header = (u32 *)tmp;
-               if (initrd_header[0] == 0x494E5244) {
-                       initrd_start = (unsigned long)&initrd_header[2];
-                       initrd_end = initrd_start + initrd_header[1];
-                       reserved_end = max(reserved_end, initrd_end);
-                       initrd_reserve_bootmem = 1;
-               }
-       }
-#endif /* CONFIG_BLK_DEV_INITRD */
 
        /*
-        * Partially used pages are not usable - thus
-        * we are rounding upwards.
+        * Init any data related to initrd. It's a nop if INITRD is
+        * not selected. Once that done we can determine the low bound
+        * of usable memory.
         */
-       start_pfn = PFN_UP(CPHYSADDR(reserved_end));
+       reserved_end = init_initrd();
+       reserved_end = PFN_UP(CPHYSADDR(max(reserved_end, (unsigned long)&_end)));
 
-#ifndef CONFIG_SGI_IP27
-       /* Find the highest page frame number we have available.  */
-       max_pfn = 0;
-       first_usable_pfn = -1UL;
+       /*
+        * Find the highest page frame number we have available.
+        */
        for (i = 0; i < boot_mem_map.nr_map; i++) {
                unsigned long start, end;
 
@@ -312,56 +269,38 @@ static inline void bootmem_init(void)
 
                start = PFN_UP(boot_mem_map.map[i].addr);
                end = PFN_DOWN(boot_mem_map.map[i].addr
-                     + boot_mem_map.map[i].size);
+                               + boot_mem_map.map[i].size);
 
-               if (start >= end)
+               if (end > highest)
+                       highest = end;
+               if (end <= reserved_end)
                        continue;
-               if (end > max_pfn)
-                       max_pfn = end;
-               if (start < first_usable_pfn) {
-                       if (start > start_pfn) {
-                               first_usable_pfn = start;
-                       } else if (end > start_pfn) {
-                               first_usable_pfn = start_pfn;
-                       }
-               }
+               if (start >= mapstart)
+                       continue;
+               mapstart = max(reserved_end, start);
        }
 
        /*
         * Determine low and high memory ranges
         */
-       max_low_pfn = max_pfn;
-       if (max_low_pfn > MAXMEM_PFN) {
-               max_low_pfn = MAXMEM_PFN;
-#ifndef CONFIG_HIGHMEM
-               /* Maximum memory usable is what is directly addressable */
-               printk(KERN_WARNING "Warning only %ldMB will be used.\n",
-                      MAXMEM >> 20);
-               printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+       if (highest > PFN_DOWN(HIGHMEM_START)) {
+#ifdef CONFIG_HIGHMEM
+               highstart_pfn = PFN_DOWN(HIGHMEM_START);
+               highend_pfn = highest;
 #endif
+               highest = PFN_DOWN(HIGHMEM_START);
        }
 
-#ifdef CONFIG_HIGHMEM
        /*
-        * Crude, we really should make a better attempt at detecting
-        * highstart_pfn
+        * Initialize the boot-time allocator with low memory only.
         */
-       highstart_pfn = highend_pfn = max_pfn;
-       if (max_pfn > MAXMEM_PFN) {
-               highstart_pfn = MAXMEM_PFN;
-               printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
-                      (highend_pfn - highstart_pfn) >> (20 - PAGE_SHIFT));
-       }
-#endif
-
-       /* Initialize the boot-time allocator with low memory only.  */
-       bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn);
+       bootmap_size = init_bootmem(mapstart, highest);
 
        /*
         * Register fully available low RAM pages with the bootmem allocator.
         */
        for (i = 0; i < boot_mem_map.nr_map; i++) {
-               unsigned long curr_pfn, last_pfn, size;
+               unsigned long start, end, size;
 
                /*
                 * Reserve usable memory.
@@ -369,85 +308,50 @@ static inline void bootmem_init(void)
                if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
                        continue;
 
-               /*
-                * We are rounding up the start address of usable memory:
-                */
-               curr_pfn = PFN_UP(boot_mem_map.map[i].addr);
-               if (curr_pfn >= max_low_pfn)
-                       continue;
-               if (curr_pfn < start_pfn)
-                       curr_pfn = start_pfn;
-
-               /*
-                * ... and at the end of the usable range downwards:
-                */
-               last_pfn = PFN_DOWN(boot_mem_map.map[i].addr
+               start = PFN_UP(boot_mem_map.map[i].addr);
+               end   = PFN_DOWN(boot_mem_map.map[i].addr
                                    + boot_mem_map.map[i].size);
-
-               if (last_pfn > max_low_pfn)
-                       last_pfn = max_low_pfn;
-
                /*
-                * Only register lowmem part of lowmem segment with bootmem.
+                * We are rounding up the start address of usable memory
+                * and at the end of the usable range downwards.
                 */
-               size = last_pfn - curr_pfn;
-               if (curr_pfn > PFN_DOWN(HIGHMEM_START))
-                       continue;
-               if (curr_pfn + size - 1 > PFN_DOWN(HIGHMEM_START))
-                       size = PFN_DOWN(HIGHMEM_START) - curr_pfn;
-               if (!size)
+               if (start >= max_low_pfn)
                        continue;
+               if (start < reserved_end)
+                       start = reserved_end;
+               if (end > max_low_pfn)
+                       end = max_low_pfn;
 
                /*
-                * ... finally, did all the rounding and playing
-                * around just make the area go away?
+                * ... finally, is the area going away?
                 */
-               if (last_pfn <= curr_pfn)
+               if (end <= start)
                        continue;
+               size = end - start;
 
                /* Register lowmem ranges */
-               free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
-               memory_present(0, curr_pfn, curr_pfn + size - 1);
+               free_bootmem(PFN_PHYS(start), size << PAGE_SHIFT);
+               memory_present(0, start, end);
        }
 
-       /* Reserve the bootmap memory.  */
-       reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
-#endif /* CONFIG_SGI_IP27 */
-
-#ifdef CONFIG_BLK_DEV_INITRD
-       initrd_below_start_ok = 1;
-       if (initrd_start) {
-               unsigned long initrd_size = ((unsigned char *)initrd_end) -
-                       ((unsigned char *)initrd_start);
-               const int width = sizeof(long) * 2;
-
-               printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
-                      (void *)initrd_start, initrd_size);
-
-               if (CPHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) {
-                       printk("initrd extends beyond end of memory "
-                              "(0x%0*Lx > 0x%0*Lx)\ndisabling initrd\n",
-                              width,
-                              (unsigned long long) CPHYSADDR(initrd_end),
-                              width,
-                              (unsigned long long) PFN_PHYS(max_low_pfn));
-                       initrd_start = initrd_end = 0;
-                       initrd_reserve_bootmem = 0;
-               }
+       /*
+        * Reserve the bootmap memory.
+        */
+       reserve_bootmem(PFN_PHYS(mapstart), bootmap_size);
 
-               if (initrd_reserve_bootmem)
-                       reserve_bootmem(CPHYSADDR(initrd_start), initrd_size);
-       }
-#endif /* CONFIG_BLK_DEV_INITRD  */
+       /*
+        * Reserve initrd memory if needed.
+        */
+       finalize_initrd();
 }
 
+#endif /* CONFIG_SGI_IP27 */
+
 /*
  * arch_mem_init - initialize memory managment subsystem
  *
  *  o plat_mem_setup() detects the memory configuration and will record detected
  *    memory areas using add_memory_region.
- *  o parse_cmdline_early() parses the command line for mem= options which,
- *    iff detected, will override the results of the automatic detection.
  *
  * At this stage the memory configuration of the system is known to the
  * kernel but generic memory managment system is still entirely uninitialized.
@@ -465,25 +369,59 @@ static inline void bootmem_init(void)
  * initialization hook for anything else was introduced.
  */
 
-extern void plat_mem_setup(void);
+static int usermem __initdata = 0;
+
+static int __init early_parse_mem(char *p)
+{
+       unsigned long start, size;
+
+       /*
+        * If a user specifies memory size, we
+        * blow away any automatically generated
+        * size.
+        */
+       if (usermem == 0) {
+               boot_mem_map.nr_map = 0;
+               usermem = 1;
+       }
+       start = 0;
+       size = memparse(p, &p);
+       if (*p == '@')
+               start = memparse(p + 1, &p);
+
+       add_memory_region(start, size, BOOT_MEM_RAM);
+       return 0;
+}
+early_param("mem", early_parse_mem);
 
 static void __init arch_mem_init(char **cmdline_p)
 {
+       extern void plat_mem_setup(void);
+
        /* call board setup routine */
        plat_mem_setup();
 
+       printk("Determined physical RAM map:\n");
+       print_memory_map();
+
        strlcpy(command_line, arcs_cmdline, sizeof(command_line));
        strlcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
 
        *cmdline_p = command_line;
 
-       parse_cmdline_early();
+       parse_early_param();
+
+       if (usermem) {
+               printk("User-defined physical RAM map:\n");
+               print_memory_map();
+       }
+
        bootmem_init();
        sparse_init();
        paging_init();
 }
 
-static inline void resource_init(void)
+static void __init resource_init(void)
 {
        int i;
 
@@ -504,10 +442,10 @@ static inline void resource_init(void)
 
                start = boot_mem_map.map[i].addr;
                end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1;
-               if (start >= MAXMEM)
+               if (start >= HIGHMEM_START)
                        continue;
-               if (end >= MAXMEM)
-                       end = MAXMEM - 1;
+               if (end >= HIGHMEM_START)
+                       end = HIGHMEM_START - 1;
 
                res = alloc_bootmem(sizeof(struct resource));
                switch (boot_mem_map.map[i].type) {
@@ -536,9 +474,6 @@ static inline void resource_init(void)
        }
 }
 
-#undef MAXMEM
-#undef MAXMEM_PFN
-
 void __init setup_arch(char **cmdline_p)
 {
        cpu_probe();
index 6b4d9be31615b3325d50d6fb48c6627c7f748850..b9d358e052144bb501956da1afca37553ab58394 100644 (file)
@@ -424,15 +424,11 @@ void do_signal(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (try_to_freeze())
-               goto no_signal;
-
        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                oldset = &current->saved_sigmask;
        else
                oldset = &current->blocked;
 
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
@@ -446,9 +442,10 @@ void do_signal(struct pt_regs *regs)
                        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                                clear_thread_flag(TIF_RESTORE_SIGMASK);
                }
+
+               return;
        }
 
-no_signal:
        /*
         * Who's code doesn't conform to the restartable syscall convention
         * dies here!!!  The li instruction, a single machine instruction,
@@ -466,6 +463,7 @@ no_signal:
                        regs->regs[7] = regs->regs[26];
                        regs->cp0_epc -= 4;
                }
+               regs->regs[0] = 0;      /* Don't deal with this again.  */
        }
 
        /*
index f32a22997c3d68d1754f745564b9dbac4e3928d2..c86a5ddff050a78661eced6ca74a68b5358b5187 100644 (file)
@@ -815,9 +815,6 @@ void do_signal32(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (try_to_freeze())
-               goto no_signal;
-
        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                oldset = &current->saved_sigmask;
        else
@@ -836,9 +833,10 @@ void do_signal32(struct pt_regs *regs)
                        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                                clear_thread_flag(TIF_RESTORE_SIGMASK);
                }
+
+               return;
        }
 
-no_signal:
        /*
         * Who's code doesn't conform to the restartable syscall convention
         * dies here!!!  The li instruction, a single machine instruction,
@@ -856,6 +854,7 @@ no_signal:
                        regs->regs[7] = regs->regs[26];
                        regs->cp0_epc -= 4;
                }
+               regs->regs[0] = 0;      /* Don't deal with this again.  */
        }
 
        /*
index 93429a4d301296d2b550ce34d8f254ea93aaa8aa..766253c44f3fd8d3dcae954755702e13bb78506a 100644 (file)
@@ -203,7 +203,7 @@ void plat_smp_setup(void)
                                write_vpe_c0_config( read_c0_config());
 
                                /* make sure there are no software interrupts pending */
-                               write_vpe_c0_cause(read_vpe_c0_cause() & ~(C_SW1|C_SW0));
+                               write_vpe_c0_cause(0);
 
                                /* Propagate Config7 */
                                write_vpe_c0_config7(read_c0_config7());
index 4cc3dea36612556925aa199e2a150d5e1918b5e4..76cb31d574824a3bb6f876d10ebacb470a0a02a6 100644 (file)
@@ -8,7 +8,7 @@
 #include <asm/regdef.h>
 #include <asm/asmmacro.h>
 #include <asm/stackframe.h>
-#include <asm/stackframe.h>
+#include <asm/irqflags.h>
 
 /*
  * "Software Interrupt" linkage.
index 0721314db6573b4c0efcd2d35dc458ee99d09474..9951240cc3fd23fde7c356542534de4c79a904af 100644 (file)
@@ -263,7 +263,7 @@ asmlinkage int sys_olduname(struct oldold_utsname __user * name)
        return error;
 }
 
-void sys_set_thread_area(unsigned long addr)
+asmlinkage int sys_set_thread_area(unsigned long addr)
 {
        struct thread_info *ti = task_thread_info(current);
 
@@ -271,6 +271,8 @@ void sys_set_thread_area(unsigned long addr)
 
        /* If some future MIPS implementation has this register in hardware,
         * we will need to update it here (and in context switches).  */
+
+       return 0;
 }
 
 asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
index 954a198494efb4b0569c5636a415ac1c17da8373..e51d8fd9a15234ec4d3e5fabcafb22b24010f6ed 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/spinlock.h>
 #include <linux/kallsyms.h>
 #include <linux/bootmem.h>
+#include <linux/interrupt.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
@@ -72,28 +73,68 @@ void (*board_nmi_handler_setup)(void);
 void (*board_ejtag_handler_setup)(void);
 void (*board_bind_eic_interrupt)(int irq, int regset);
 
-/*
- * These constant is for searching for possible module text segments.
- * MODULE_RANGE is a guess of how much space is likely to be vmalloced.
- */
-#define MODULE_RANGE (8*1024*1024)
+
+static void show_raw_backtrace(unsigned long reg29)
+{
+       unsigned long *sp = (unsigned long *)reg29;
+       unsigned long addr;
+
+       printk("Call Trace:");
+#ifdef CONFIG_KALLSYMS
+       printk("\n");
+#endif
+       while (!kstack_end(sp)) {
+               addr = *sp++;
+               if (__kernel_text_address(addr))
+                       print_ip_sym(addr);
+       }
+       printk("\n");
+}
+
+#ifdef CONFIG_KALLSYMS
+static int raw_show_trace;
+static int __init set_raw_show_trace(char *str)
+{
+       raw_show_trace = 1;
+       return 1;
+}
+__setup("raw_show_trace", set_raw_show_trace);
+
+extern unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
+                                 unsigned long pc, unsigned long ra);
+
+static void show_backtrace(struct task_struct *task, struct pt_regs *regs)
+{
+       unsigned long sp = regs->regs[29];
+       unsigned long ra = regs->regs[31];
+       unsigned long pc = regs->cp0_epc;
+
+       if (raw_show_trace || !__kernel_text_address(pc)) {
+               show_raw_backtrace(sp);
+               return;
+       }
+       printk("Call Trace:\n");
+       do {
+               print_ip_sym(pc);
+               pc = unwind_stack(task, &sp, pc, ra);
+               ra = 0;
+       } while (pc);
+       printk("\n");
+}
+#else
+#define show_backtrace(task, r) show_raw_backtrace((r)->regs[29]);
+#endif
 
 /*
  * This routine abuses get_user()/put_user() to reference pointers
  * with at least a bit of error checking ...
  */
-void show_stack(struct task_struct *task, unsigned long *sp)
+static void show_stacktrace(struct task_struct *task, struct pt_regs *regs)
 {
        const int field = 2 * sizeof(unsigned long);
        long stackdata;
        int i;
-
-       if (!sp) {
-               if (task && task != current)
-                       sp = (unsigned long *) task->thread.reg29;
-               else
-                       sp = (unsigned long *) &sp;
-       }
+       unsigned long *sp = (unsigned long *)regs->regs[29];
 
        printk("Stack :");
        i = 0;
@@ -114,32 +155,48 @@ void show_stack(struct task_struct *task, unsigned long *sp)
                i++;
        }
        printk("\n");
+       show_backtrace(task, regs);
 }
 
-void show_trace(struct task_struct *task, unsigned long *stack)
+static __always_inline void prepare_frametrace(struct pt_regs *regs)
 {
-       const int field = 2 * sizeof(unsigned long);
-       unsigned long addr;
-
-       if (!stack) {
-               if (task && task != current)
-                       stack = (unsigned long *) task->thread.reg29;
-               else
-                       stack = (unsigned long *) &stack;
-       }
-
-       printk("Call Trace:");
-#ifdef CONFIG_KALLSYMS
-       printk("\n");
+       __asm__ __volatile__(
+               ".set push\n\t"
+               ".set noat\n\t"
+#ifdef CONFIG_64BIT
+               "1: dla $1, 1b\n\t"
+               "sd $1, %0\n\t"
+               "sd $29, %1\n\t"
+               "sd $31, %2\n\t"
+#else
+               "1: la $1, 1b\n\t"
+               "sw $1, %0\n\t"
+               "sw $29, %1\n\t"
+               "sw $31, %2\n\t"
 #endif
-       while (!kstack_end(stack)) {
-               addr = *stack++;
-               if (__kernel_text_address(addr)) {
-                       printk(" [<%0*lx>] ", field, addr);
-                       print_symbol("%s\n", addr);
+               ".set pop\n\t"
+               : "=m" (regs->cp0_epc),
+               "=m" (regs->regs[29]), "=m" (regs->regs[31])
+               : : "memory");
+}
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+       struct pt_regs regs;
+       if (sp) {
+               regs.regs[29] = (unsigned long)sp;
+               regs.regs[31] = 0;
+               regs.cp0_epc = 0;
+       } else {
+               if (task && task != current) {
+                       regs.regs[29] = task->thread.reg29;
+                       regs.regs[31] = 0;
+                       regs.cp0_epc = task->thread.reg31;
+               } else {
+                       prepare_frametrace(&regs);
                }
        }
-       printk("\n");
+       show_stacktrace(task, &regs);
 }
 
 /*
@@ -147,9 +204,15 @@ void show_trace(struct task_struct *task, unsigned long *stack)
  */
 void dump_stack(void)
 {
-       unsigned long stack;
+       struct pt_regs regs;
 
-       show_trace(current, &stack);
+       /*
+        * Remove any garbage that may be in regs (specially func
+        * addresses) to avoid show_raw_backtrace() to report them
+        */
+       memset(&regs, 0, sizeof(regs));
+       prepare_frametrace(&regs);
+       show_backtrace(current, &regs);
 }
 
 EXPORT_SYMBOL(dump_stack);
@@ -268,8 +331,7 @@ void show_registers(struct pt_regs *regs)
        print_modules();
        printk("Process %s (pid: %d, threadinfo=%p, task=%p)\n",
                current->comm, current->pid, current_thread_info(), current);
-       show_stack(current, (long *) regs->regs[29]);
-       show_trace(current, (long *) regs->regs[29]);
+       show_stacktrace(current, regs);
        show_code((unsigned int *) regs->cp0_epc);
        printk("\n");
 }
@@ -292,6 +354,16 @@ NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
        printk("%s[#%d]:\n", str, ++die_counter);
        show_registers(regs);
        spin_unlock_irq(&die_lock);
+
+       if (in_interrupt())
+               panic("Fatal exception in interrupt");
+
+       if (panic_on_oops) {
+               printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
+               ssleep(5);
+               panic("Fatal exception");
+       }
+
        do_exit(SIGSEGV);
 }
 
index 9ee0ec2cd067ccb31e787b9ba2fbe30b6b0df52b..51ddd216689850d5d0113dee662782ef82c3da8f 100644 (file)
@@ -768,10 +768,16 @@ int vpe_run(struct vpe * v)
         */
        write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | v->minor);
 
+       write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() & ~(VPECONF0_VPA));
+
+       back_to_back_c0_hazard();
+
         /* Set up the XTC bit in vpeconf0 to point at our tc */
         write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
                                | (t->index << VPECONF0_XTC_SHIFT));
 
+       back_to_back_c0_hazard();
+
         /* enable this VPE */
         write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
 
index fb25e0377f11b3097d9dc46b1151083dac590eee..a020a3cb4f4bc4767130546fc287f0c09f1cb049 100644 (file)
@@ -1,6 +1,8 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 1999, 2000, 2006  MIPS Technologies, Inc.
+ *     All rights reserved.
+ *     Authors: Carsten Langgaard <carstenl@mips.com>
+ *              Maciej W. Rozycki <macro@mips.com>
  *
  * ########################################################################
  *
  */
 #include <linux/compiler.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 
-#include <asm/irq.h>
+#include <asm/gdb-stub.h>
 #include <asm/io.h>
+#include <asm/irq_cpu.h>
+#include <asm/msc01_ic.h>
+
 #include <asm/mips-boards/atlas.h>
 #include <asm/mips-boards/atlasint.h>
-#include <asm/gdb-stub.h>
-
+#include <asm/mips-boards/generic.h>
 
 static struct atlas_ictrl_regs *atlas_hw0_icregs;
 
@@ -47,13 +52,13 @@ static struct atlas_ictrl_regs *atlas_hw0_icregs;
 
 void disable_atlas_irq(unsigned int irq_nr)
 {
-       atlas_hw0_icregs->intrsten = (1 << (irq_nr-ATLASINT_BASE));
+       atlas_hw0_icregs->intrsten = 1 << (irq_nr - ATLAS_INT_BASE);
        iob();
 }
 
 void enable_atlas_irq(unsigned int irq_nr)
 {
-       atlas_hw0_icregs->intseten = (1 << (irq_nr-ATLASINT_BASE));
+       atlas_hw0_icregs->intseten = 1 << (irq_nr - ATLAS_INT_BASE);
        iob();
 }
 
@@ -107,7 +112,7 @@ static inline void atlas_hw0_irqdispatch(struct pt_regs *regs)
        if (unlikely(int_status == 0))
                return;
 
-       irq = ATLASINT_BASE + ls1bit32(int_status);
+       irq = ATLAS_INT_BASE + ls1bit32(int_status);
 
        DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq);
 
@@ -161,15 +166,14 @@ static inline unsigned int irq_ffs(unsigned int pending)
 }
 
 /*
- * IRQs on the Atlas board look basically (barring software IRQs which we
- * don't use at all and all external interrupt sources are combined together
- * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ * IRQs on the Atlas board look basically like (all external interrupt
+ * sources are combined together on hardware interrupt 0 (MIPS IRQ 2)):
  *
- *     MIPS IRQ        Source
+ *      MIPS IRQ        Source
  *      --------        ------
- *             0       Software (ignored)
- *             1        Software (ignored)
- *             2        Combined hardware interrupt (hw0)
+ *             0        Software 0 (reschedule IPI on MT)
+ *             1        Software 1 (remote call IPI on MT)
+ *             2        Combined Atlas hardware interrupt (hw0)
  *             3        Hardware (ignored)
  *             4        Hardware (ignored)
  *             5        Hardware (ignored)
@@ -179,7 +183,7 @@ static inline unsigned int irq_ffs(unsigned int pending)
  * We handle the IRQ according to _our_ priority which is:
  *
  * Highest ----     R4k Timer
- * Lowest  ----     Combined hardware interrupt
+ * Lowest  ----     Software 0
  *
  * then we just return, if multiple IRQs are pending then we will just take
  * another exception, big deal.
@@ -193,17 +197,19 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 
        if (irq == MIPSCPU_INT_ATLAS)
                atlas_hw0_irqdispatch(regs);
-       else if (irq > 0)
+       else if (irq >= 0)
                do_IRQ(MIPSCPU_INT_BASE + irq, regs);
        else
                spurious_interrupt(regs);
 }
 
-void __init arch_init_irq(void)
+static inline void init_atlas_irqs (int base)
 {
        int i;
 
-       atlas_hw0_icregs = (struct atlas_ictrl_regs *)ioremap (ATLAS_ICTRL_REGS_BASE, sizeof(struct atlas_ictrl_regs *));
+       atlas_hw0_icregs = (struct atlas_ictrl_regs *)
+                          ioremap(ATLAS_ICTRL_REGS_BASE,
+                                  sizeof(struct atlas_ictrl_regs *));
 
        /*
         * Mask out all interrupt by writing "1" to all bit position in
@@ -211,7 +217,7 @@ void __init arch_init_irq(void)
         */
        atlas_hw0_icregs->intrsten = 0xffffffff;
 
-       for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
+       for (i = ATLAS_INT_BASE; i <= ATLAS_INT_END; i++) {
                irq_desc[i].status      = IRQ_DISABLED;
                irq_desc[i].action      = 0;
                irq_desc[i].depth       = 1;
@@ -219,3 +225,62 @@ void __init arch_init_irq(void)
                spin_lock_init(&irq_desc[i].lock);
        }
 }
+
+static struct irqaction atlasirq = {
+       .handler = no_action,
+       .name = "Atlas cascade"
+};
+
+msc_irqmap_t __initdata msc_irqmap[] = {
+       {MSC01C_INT_TMR,                MSC01_IRQ_EDGE, 0},
+       {MSC01C_INT_PCI,                MSC01_IRQ_LEVEL, 0},
+};
+int __initdata msc_nr_irqs = sizeof(msc_irqmap) / sizeof(*msc_irqmap);
+
+msc_irqmap_t __initdata msc_eicirqmap[] = {
+       {MSC01E_INT_SW0,                MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_SW1,                MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_ATLAS,              MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_TMR,                MSC01_IRQ_EDGE, 0},
+       {MSC01E_INT_PCI,                MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_PERFCTR,            MSC01_IRQ_LEVEL, 0},
+       {MSC01E_INT_CPUCTR,             MSC01_IRQ_LEVEL, 0}
+};
+int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap) / sizeof(*msc_eicirqmap);
+
+void __init arch_init_irq(void)
+{
+       init_atlas_irqs(ATLAS_INT_BASE);
+
+       if (!cpu_has_veic)
+               mips_cpu_irq_init(MIPSCPU_INT_BASE);
+
+       switch(mips_revision_corid) {
+       case MIPS_REVISION_CORID_CORE_MSC:
+       case MIPS_REVISION_CORID_CORE_FPGA2:
+       case MIPS_REVISION_CORID_CORE_FPGA3:
+       case MIPS_REVISION_CORID_CORE_24K:
+       case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+               if (cpu_has_veic)
+                       init_msc_irqs (MSC01E_INT_BASE,
+                                      msc_eicirqmap, msc_nr_eicirqs);
+               else
+                       init_msc_irqs (MSC01C_INT_BASE,
+                                      msc_irqmap, msc_nr_irqs);
+       }
+
+
+       if (cpu_has_veic) {
+               set_vi_handler (MSC01E_INT_ATLAS, atlas_hw0_irqdispatch);
+               setup_irq (MSC01E_INT_BASE + MSC01E_INT_ATLAS, &atlasirq);
+       } else if (cpu_has_vint) {
+               set_vi_handler (MIPSCPU_INT_ATLAS, atlas_hw0_irqdispatch);
+#ifdef CONFIG_MIPS_MT_SMTC
+               setup_irq_smtc (MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS,
+                               &atlasirq, (0x100 << MIPSCPU_INT_ATLAS));
+#else /* Not SMTC */
+               setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+#endif /* CONFIG_MIPS_MT_SMTC */
+       } else
+               setup_irq(MIPSCPU_INT_BASE + MIPSCPU_INT_ATLAS, &atlasirq);
+}
index 9871a91fdb07a1da931be6d5d46ecdb83efe4354..0c6b0ce15028827c6e1e069bcf2ee497d23dfc3b 100644 (file)
@@ -77,7 +77,7 @@ static void __init serial_init(void)
 #else
        s.iobase = ATLAS_UART_REGS_BASE+3;
 #endif
-       s.irq = ATLASINT_UART;
+       s.irq = ATLAS_INT_UART;
        s.uartclk = ATLAS_BASE_BAUD * 16;
        s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_AUTO_IRQ;
        s.iotype = UPIO_PORT;
index 557bf961f36a34ad1f4b8e9484565abefbcd37de..8d15861fce618248aeab570ccee13ef637bd769f 100644 (file)
 
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/prom.h>
+
+#ifdef CONFIG_MIPS_ATLAS
+#include <asm/mips-boards/atlasint.h>
+#endif
+#ifdef CONFIG_MIPS_MALTA
 #include <asm/mips-boards/maltaint.h>
-#include <asm/mc146818-time.h>
+#endif
 
 unsigned long cpu_khz;
 
@@ -92,10 +97,9 @@ extern int (*perf_irq)(struct pt_regs *regs);
 irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        int cpu = smp_processor_id();
-       int r2 = cpu_has_mips_r2;
 
 #ifdef CONFIG_MIPS_MT_SMTC
-        /*
+       /*
         *  In an SMTC system, one Count/Compare set exists per VPE.
         *  Which TC within a VPE gets the interrupt is essentially
         *  random - we only know that it shouldn't be one with
@@ -108,29 +112,46 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
         *  the general MIPS timer_interrupt routine.
         */
 
+       int vpflags;
+
        /*
-        * DVPE is necessary so long as cross-VPE interrupts
-        * are done via read-modify-write of Cause register.
+        * We could be here due to timer interrupt,
+        * perf counter overflow, or both.
         */
-       int vpflags = dvpe();
-       write_c0_compare (read_c0_count() - 1);
-       clear_c0_cause(CPUCTR_IMASKBIT);
-       evpe(vpflags);
+       if (read_c0_cause() & (1 << 26))
+               perf_irq(regs);
 
-       if (cpu_data[cpu].vpe_id == 0) {
-               timer_interrupt(irq, dev_id, regs);
-               scroll_display_message();
-       } else
-               write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
-       smtc_timer_broadcast(cpu_data[cpu].vpe_id);
-
-       if (cpu != 0)
+       if (read_c0_cause() & (1 << 30)) {
+               /* If timer interrupt, make it de-assert */
+               write_c0_compare (read_c0_count() - 1);
                /*
-                * Other CPUs should do profiling and process accounting
+                * DVPE is necessary so long as cross-VPE interrupts
+                * are done via read-modify-write of Cause register.
                 */
-               local_timer_interrupt(irq, dev_id, regs);
-
+               vpflags = dvpe();
+               clear_c0_cause(CPUCTR_IMASKBIT);
+               evpe(vpflags);
+               /*
+                * There are things we only want to do once per tick
+                * in an "MP" system.   One TC of each VPE will take
+                * the actual timer interrupt.  The others will get
+                * timer broadcast IPIs. We use whoever it is that takes
+                * the tick on VPE 0 to run the full timer_interrupt().
+                */
+               if (cpu_data[cpu].vpe_id == 0) {
+                               timer_interrupt(irq, NULL, regs);
+                               smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+                               scroll_display_message();
+               } else {
+                       write_c0_compare(read_c0_count() +
+                                        (mips_hpt_frequency/HZ));
+                       local_timer_interrupt(irq, dev_id, regs);
+                       smtc_timer_broadcast(cpu_data[cpu].vpe_id);
+               }
+       }
 #else /* CONFIG_MIPS_MT_SMTC */
+       int r2 = cpu_has_mips_r2;
+
        if (cpu == 0) {
                /*
                 * CPU 0 handles the global timer interrupt job and process
@@ -161,9 +182,8 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                 */
                local_timer_interrupt(irq, dev_id, regs);
        }
-#endif /* CONFIG_MIPS_MT_SMTC */
-
 out:
+#endif /* CONFIG_MIPS_MT_SMTC */
        return IRQ_HANDLED;
 }
 
index bb041a22f20a55dd35f9eb28ffb3e5073abff1e8..e1f35ef81145445c5530ccbdca83b4715a040c2d 100644 (file)
@@ -335,7 +335,7 @@ void __init r3k_cache_init(void)
        flush_cache_mm = r3k_flush_cache_mm;
        flush_cache_range = r3k_flush_cache_range;
        flush_cache_page = r3k_flush_cache_page;
-       flush_icache_page = r3k_flush_icache_page;
+       __flush_icache_page = r3k_flush_icache_page;
        flush_icache_range = r3k_flush_icache_range;
 
        flush_cache_sigtramp = r3k_flush_cache_sigtramp;
index 069803f58f3b2bb2c47676d49d574f15d45433cf..0b2da53750bd4220a30d1e97d7016d436a41ce6e 100644 (file)
@@ -89,7 +89,7 @@ static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
        blast_dcache32_page(addr);
 }
 
-static inline void r4k_blast_dcache_page_setup(void)
+static void __init r4k_blast_dcache_page_setup(void)
 {
        unsigned long  dc_lsize = cpu_dcache_line_size();
 
@@ -103,7 +103,7 @@ static inline void r4k_blast_dcache_page_setup(void)
 
 static void (* r4k_blast_dcache_page_indexed)(unsigned long addr);
 
-static inline void r4k_blast_dcache_page_indexed_setup(void)
+static void __init r4k_blast_dcache_page_indexed_setup(void)
 {
        unsigned long dc_lsize = cpu_dcache_line_size();
 
@@ -117,7 +117,7 @@ static inline void r4k_blast_dcache_page_indexed_setup(void)
 
 static void (* r4k_blast_dcache)(void);
 
-static inline void r4k_blast_dcache_setup(void)
+static void __init r4k_blast_dcache_setup(void)
 {
        unsigned long dc_lsize = cpu_dcache_line_size();
 
@@ -202,7 +202,7 @@ static inline void tx49_blast_icache32_page_indexed(unsigned long page)
 
 static void (* r4k_blast_icache_page)(unsigned long addr);
 
-static inline void r4k_blast_icache_page_setup(void)
+static void __init r4k_blast_icache_page_setup(void)
 {
        unsigned long ic_lsize = cpu_icache_line_size();
 
@@ -219,7 +219,7 @@ static inline void r4k_blast_icache_page_setup(void)
 
 static void (* r4k_blast_icache_page_indexed)(unsigned long addr);
 
-static inline void r4k_blast_icache_page_indexed_setup(void)
+static void __init r4k_blast_icache_page_indexed_setup(void)
 {
        unsigned long ic_lsize = cpu_icache_line_size();
 
@@ -243,7 +243,7 @@ static inline void r4k_blast_icache_page_indexed_setup(void)
 
 static void (* r4k_blast_icache)(void);
 
-static inline void r4k_blast_icache_setup(void)
+static void __init r4k_blast_icache_setup(void)
 {
        unsigned long ic_lsize = cpu_icache_line_size();
 
@@ -264,7 +264,7 @@ static inline void r4k_blast_icache_setup(void)
 
 static void (* r4k_blast_scache_page)(unsigned long addr);
 
-static inline void r4k_blast_scache_page_setup(void)
+static void __init r4k_blast_scache_page_setup(void)
 {
        unsigned long sc_lsize = cpu_scache_line_size();
 
@@ -282,7 +282,7 @@ static inline void r4k_blast_scache_page_setup(void)
 
 static void (* r4k_blast_scache_page_indexed)(unsigned long addr);
 
-static inline void r4k_blast_scache_page_indexed_setup(void)
+static void __init r4k_blast_scache_page_indexed_setup(void)
 {
        unsigned long sc_lsize = cpu_scache_line_size();
 
@@ -300,7 +300,7 @@ static inline void r4k_blast_scache_page_indexed_setup(void)
 
 static void (* r4k_blast_scache)(void);
 
-static inline void r4k_blast_scache_setup(void)
+static void __init r4k_blast_scache_setup(void)
 {
        unsigned long sc_lsize = cpu_scache_line_size();
 
@@ -475,7 +475,7 @@ static inline void local_r4k_flush_cache_page(void *args)
                }
        }
        if (exec) {
-               if (cpu_has_vtag_icache) {
+               if (cpu_has_vtag_icache && mm == current->active_mm) {
                        int cpu = smp_processor_id();
 
                        if (cpu_context(cpu, mm) != 0)
@@ -599,7 +599,7 @@ static inline void local_r4k_flush_icache_page(void *args)
         * We're not sure of the virtual address(es) involved here, so
         * we have to flush the entire I-cache.
         */
-       if (cpu_has_vtag_icache) {
+       if (cpu_has_vtag_icache && vma->vm_mm == current->active_mm) {
                int cpu = smp_processor_id();
 
                if (cpu_context(cpu, vma->vm_mm) != 0)
@@ -1221,7 +1221,7 @@ void au1x00_fixup_config_od(void)
        }
 }
 
-static inline void coherency_setup(void)
+static void __init coherency_setup(void)
 {
        change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT);
 
@@ -1242,7 +1242,7 @@ static inline void coherency_setup(void)
                clear_c0_config(CONF_CU);
                break;
        /*
-        * We need to catch the ealry Alchemy SOCs with
+        * We need to catch the early Alchemy SOCs with
         * the write-only co_config.od bit and set it back to one...
         */
        case CPU_AU1000: /* rev. DA, HA, HB */
@@ -1291,7 +1291,7 @@ void __init r4k_cache_init(void)
        __flush_cache_all       = r4k___flush_cache_all;
        flush_cache_mm          = r4k_flush_cache_mm;
        flush_cache_page        = r4k_flush_cache_page;
-       flush_icache_page       = r4k_flush_icache_page;
+       __flush_icache_page     = r4k_flush_icache_page;
        flush_cache_range       = r4k_flush_cache_range;
 
        flush_cache_sigtramp    = r4k_flush_cache_sigtramp;
index 2d71efb82ac568be0771e52be3702cbc02a39c5d..16bad7c0a63f876ec0555c247607512bae82dc8a 100644 (file)
@@ -154,6 +154,26 @@ static inline void __sb1_flush_icache_all(void)
        }
 }
 
+/*
+ * Invalidate a range of the icache.  The addresses are virtual, and
+ * the cache is virtually indexed and tagged.  However, we don't
+ * necessarily have the right ASID context, so use index ops instead
+ * of hit ops.
+ */
+static inline void __sb1_flush_icache_range(unsigned long start,
+       unsigned long end)
+{
+       start &= ~(icache_line_size - 1);
+       end = (end + icache_line_size - 1) & ~(icache_line_size - 1);
+
+       while (start != end) {
+               cache_set_op(Index_Invalidate_I, start & icache_index_mask);
+               start += icache_line_size;
+       }
+       mispredict();
+       sync();
+}
+
 /*
  * Flush the icache for a given physical page.  Need to writeback the
  * dcache first, then invalidate the icache.  If the page isn't
@@ -173,8 +193,11 @@ static void local_sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long
        /*
         * Bumping the ASID is probably cheaper than the flush ...
         */
-       if (cpu_context(cpu, vma->vm_mm) != 0)
-               drop_mmu_context(vma->vm_mm, cpu);
+       if (vma->vm_mm == current->active_mm) {
+               if (cpu_context(cpu, vma->vm_mm) != 0)
+                       drop_mmu_context(vma->vm_mm, cpu);
+       } else
+               __sb1_flush_icache_range(addr, addr + PAGE_SIZE);
 }
 
 #ifdef CONFIG_SMP
@@ -210,26 +233,6 @@ void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsign
        __attribute__((alias("local_sb1_flush_cache_page")));
 #endif
 
-/*
- * Invalidate a range of the icache.  The addresses are virtual, and
- * the cache is virtually indexed and tagged.  However, we don't
- * necessarily have the right ASID context, so use index ops instead
- * of hit ops.
- */
-static inline void __sb1_flush_icache_range(unsigned long start,
-       unsigned long end)
-{
-       start &= ~(icache_line_size - 1);
-       end = (end + icache_line_size - 1) & ~(icache_line_size - 1);
-
-       while (start != end) {
-               cache_set_op(Index_Invalidate_I, start & icache_index_mask);
-               start += icache_line_size;
-       }
-       mispredict();
-       sync();
-}
-
 
 /*
  * Invalidate all caches on this CPU
@@ -326,9 +329,12 @@ static void local_sb1_flush_icache_page(struct vm_area_struct *vma,
         * If there's a context, bump the ASID (cheaper than a flush,
         * since we don't know VAs!)
         */
-       if (cpu_context(cpu, vma->vm_mm) != 0) {
-               drop_mmu_context(vma->vm_mm, cpu);
-       }
+       if (vma->vm_mm == current->active_mm) {
+               if (cpu_context(cpu, vma->vm_mm) != 0)
+                       drop_mmu_context(vma->vm_mm, cpu);
+       } else
+               __sb1_flush_icache_range(start, start + PAGE_SIZE);
+
 }
 
 #ifdef CONFIG_SMP
@@ -520,7 +526,7 @@ void sb1_cache_init(void)
 
        /* These routines are for Icache coherence with the Dcache */
        flush_icache_range = sb1_flush_icache_range;
-       flush_icache_page = sb1_flush_icache_page;
+       __flush_icache_page = sb1_flush_icache_page;
        flush_icache_all = __sb1_flush_icache_all; /* local only */
 
        /* This implies an Icache flush too, so can't be nop'ed */
index 5dfc9b1901f6537554bc7e34a1820b8cc8d5a6c0..932a09d7ef84810bdb4d43c591d63badbff3892c 100644 (file)
@@ -382,7 +382,7 @@ void __init tx39_cache_init(void)
                flush_cache_mm          = (void *) tx39h_flush_icache_all;
                flush_cache_range       = (void *) tx39h_flush_icache_all;
                flush_cache_page        = (void *) tx39h_flush_icache_all;
-               flush_icache_page       = (void *) tx39h_flush_icache_all;
+               __flush_icache_page     = (void *) tx39h_flush_icache_all;
                flush_icache_range      = (void *) tx39h_flush_icache_all;
 
                flush_cache_sigtramp    = (void *) tx39h_flush_icache_all;
@@ -408,7 +408,7 @@ void __init tx39_cache_init(void)
                flush_cache_mm = tx39_flush_cache_mm;
                flush_cache_range = tx39_flush_cache_range;
                flush_cache_page = tx39_flush_cache_page;
-               flush_icache_page = tx39_flush_icache_page;
+               __flush_icache_page = tx39_flush_icache_page;
                flush_icache_range = tx39_flush_icache_range;
 
                flush_cache_sigtramp = tx39_flush_cache_sigtramp;
index ddd3a2de1d73ea8513ace939f4c40d0fd81e2205..40c8b0235183859bfc087b72a509db11fdcd4490 100644 (file)
@@ -25,7 +25,7 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
 void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
        unsigned long pfn);
 void (*flush_icache_range)(unsigned long start, unsigned long end);
-void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
+void (*__flush_icache_page)(struct vm_area_struct *vma, struct page *page);
 
 /* MIPS specific cache operations */
 void (*flush_cache_sigtramp)(unsigned long addr);
@@ -70,6 +70,8 @@ void __flush_dcache_page(struct page *page)
        struct address_space *mapping = page_mapping(page);
        unsigned long addr;
 
+       if (PageHighMem(page))
+               return;
        if (mapping && !mapping_mapped(mapping)) {
                SetPageDcacheDirty(page);
                return;
@@ -91,16 +93,16 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address,
 {
        struct page *page;
        unsigned long pfn, addr;
+       int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc;
 
        pfn = pte_pfn(pte);
-       if (pfn_valid(pfn) && (page = pfn_to_page(pfn), page_mapping(page)) &&
-           Page_dcache_dirty(page)) {
-               if (pages_do_alias((unsigned long)page_address(page),
-                                  address & PAGE_MASK)) {
-                       addr = (unsigned long) page_address(page);
+       if (unlikely(!pfn_valid(pfn)))
+               return;
+       page = pfn_to_page(pfn);
+       if (page_mapping(page) && Page_dcache_dirty(page)) {
+               addr = (unsigned long) page_address(page);
+               if (exec || pages_do_alias(addr, address & PAGE_MASK))
                        flush_data_cache_page(addr);
-               }
-
                ClearPageDcacheDirty(page);
        }
 }
index e3a617224868f04643719e68c9020d9941688efc..a4f8c45c4e8ede95a018f85da394317a88153ba4 100644 (file)
@@ -89,7 +89,7 @@ good_area:
                if (!(vma->vm_flags & VM_WRITE))
                        goto bad_area;
        } else {
-               if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+               if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
                        goto bad_area;
        }
 
index 2cde1b77244304fdd530885c0f21e567e5fb2b56..2e0e21ef433ee1451ba4e7c125e4338b01bc64e0 100644 (file)
@@ -26,11 +26,6 @@ extern void build_tlb_refill_handler(void);
  */
 #define UNIQUE_ENTRYHI(idx) (CKSEG0 + ((idx) << (PAGE_SHIFT + 1)))
 
-/* CP0 hazard avoidance. */
-#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \
-                                    "nop; nop; nop; nop; nop; nop;\n\t" \
-                                    ".set reorder\n\t")
-
 /* Atomicity and interruptability */
 #ifdef CONFIG_MIPS_MT_SMTC
 
@@ -126,7 +121,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                                start += (PAGE_SIZE << 1);
                                mtc0_tlbw_hazard();
                                tlb_probe();
-                               BARRIER;
+                               tlb_probe_hazard();
                                idx = read_c0_index();
                                write_c0_entrylo0(0);
                                write_c0_entrylo1(0);
@@ -168,7 +163,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
                        start += (PAGE_SIZE << 1);
                        mtc0_tlbw_hazard();
                        tlb_probe();
-                       BARRIER;
+                       tlb_probe_hazard();
                        idx = read_c0_index();
                        write_c0_entrylo0(0);
                        write_c0_entrylo1(0);
@@ -202,7 +197,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
                write_c0_entryhi(page | newpid);
                mtc0_tlbw_hazard();
                tlb_probe();
-               BARRIER;
+               tlb_probe_hazard();
                idx = read_c0_index();
                write_c0_entrylo0(0);
                write_c0_entrylo1(0);
@@ -235,7 +230,7 @@ void local_flush_tlb_one(unsigned long page)
        write_c0_entryhi(page);
        mtc0_tlbw_hazard();
        tlb_probe();
-       BARRIER;
+       tlb_probe_hazard();
        idx = read_c0_index();
        write_c0_entrylo0(0);
        write_c0_entrylo1(0);
@@ -279,7 +274,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
        pgdp = pgd_offset(vma->vm_mm, address);
        mtc0_tlbw_hazard();
        tlb_probe();
-       BARRIER;
+       tlb_probe_hazard();
        pudp = pud_offset(pgdp, address);
        pmdp = pmd_offset(pudp, address);
        idx = read_c0_index();
@@ -320,7 +315,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
        pgdp = pgd_offset(vma->vm_mm, address);
        mtc0_tlbw_hazard();
        tlb_probe();
-       BARRIER;
+       tlb_probe_hazard();
        pmdp = pmd_offset(pgdp, address);
        idx = read_c0_index();
        ptep = pte_offset_map(pmdp, address);
@@ -351,7 +346,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
        wired = read_c0_wired();
        write_c0_wired(wired + 1);
        write_c0_index(wired);
-       BARRIER;
+       tlbw_use_hazard();      /* What is the hazard here? */
        write_c0_pagemask(pagemask);
        write_c0_entryhi(entryhi);
        write_c0_entrylo0(entrylo0);
@@ -361,7 +356,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
        tlbw_use_hazard();
 
        write_c0_entryhi(old_ctx);
-       BARRIER;
+       tlbw_use_hazard();      /* What is the hazard here? */
        write_c0_pagemask(old_pagemask);
        local_flush_tlb_all();
        EXIT_CRITICAL(flags);
index 35d5927706eac8701f6442fe75620fb381445599..edefa97b233098327e0b6aefbe961403491d9501 100644 (file)
@@ -11,7 +11,6 @@ obj-$(CONFIG_ITE_BOARD_GEN)   += ops-it8172.o
 obj-$(CONFIG_MIPS_BONITO64)    += ops-bonito64.o
 obj-$(CONFIG_MIPS_GT64111)     += ops-gt64111.o
 obj-$(CONFIG_MIPS_GT64120)     += ops-gt64120.o
-obj-$(CONFIG_MIPS_GT96100)     += ops-gt96100.o
 obj-$(CONFIG_PCI_MARVELL)      += ops-marvell.o
 obj-$(CONFIG_MIPS_MSC)         += ops-msc.o
 obj-$(CONFIG_MIPS_NILE4)       += ops-nile4.o
@@ -28,8 +27,7 @@ obj-$(CONFIG_DDB5477)         += fixup-ddb5477.o pci-ddb5477.o ops-ddb5477.o
 obj-$(CONFIG_LASAT)            += pci-lasat.o
 obj-$(CONFIG_MIPS_ATLAS)       += fixup-atlas.o
 obj-$(CONFIG_MIPS_COBALT)      += fixup-cobalt.o
-obj-$(CONFIG_MIPS_EV96100)     += fixup-ev64120.o
-obj-$(CONFIG_MIPS_EV96100)     += fixup-ev96100.o pci-ev96100.o
+obj-$(CONFIG_MIPS_EV64120)     += fixup-ev64120.o
 obj-$(CONFIG_MIPS_ITE8172)     += fixup-ite8172g.o
 obj-$(CONFIG_MIPS_IVR)         += fixup-ivr.o
 obj-$(CONFIG_SOC_AU1500)       += fixup-au1000.o ops-au1000.o
index 439510af30372152656f3242a6599aa603ba3679..c6cd6e9cdfbc8d4b29dc804f173e8cfbc8de596a 100644 (file)
 
 #include <asm/mips-boards/atlasint.h>
 
-#define PCIA           ATLASINT_PCIA
-#define PCIB           ATLASINT_PCIB
-#define PCIC           ATLASINT_PCIC
-#define PCID           ATLASINT_PCID
-#define INTA           ATLASINT_INTA
-#define INTB           ATLASINT_INTB
-#define ETH            ATLASINT_ETH
-#define INTC           ATLASINT_INTC
-#define SCSI           ATLASINT_SCSI
-#define INTD           ATLASINT_INTD
+#define PCIA           ATLAS_INT_PCIA
+#define PCIB           ATLAS_INT_PCIB
+#define PCIC           ATLAS_INT_PCIC
+#define PCID           ATLAS_INT_PCID
+#define INTA           ATLAS_INT_INTA
+#define INTB           ATLAS_INT_INTB
+#define ETH            ATLAS_INT_ETH
+#define INTC           ATLAS_INT_INTC
+#define SCSI           ATLAS_INT_SCSI
+#define INTD           ATLAS_INT_INTD
 
 static char irq_tab[][5] __initdata = {
        /*      INTA    INTB    INTC    INTD */
diff --git a/arch/mips/pci/fixup-ev96100.c b/arch/mips/pci/fixup-ev96100.c
deleted file mode 100644 (file)
index e2bc977..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *     EV96100 Board specific pci fixups.
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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/init.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-
-static char irq_tab_ev96100[][5] __initdata = {
- [8] = { 0, 5, 5, 5, 5 },
- [9] = { 0, 2, 2, 2, 2 }
-};
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       return irq_tab_ev96100[slot][pin];
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-       return 0;
-}
index 0c0c1e6519f9e4a35cb6a98b04b669ad4384c82a..8ae46481fcb720d98b608b5adea07458396ae59d 100644 (file)
@@ -110,7 +110,7 @@ static int config_access(unsigned char access_type, struct pci_bus *bus,
        if (first_cfg) {
                /* reserve a wired entry for pci config accesses */
                first_cfg = 0;
-               pci_cfg_vm = get_vm_area(0x2000, 0);
+               pci_cfg_vm = get_vm_area(0x2000, VM_IOREMAP);
                if (!pci_cfg_vm)
                        panic (KERN_ERR "PCI unable to get vm area\n");
                pci_cfg_wired_entry = read_c0_wired();
diff --git a/arch/mips/pci/ops-gt96100.c b/arch/mips/pci/ops-gt96100.c
deleted file mode 100644 (file)
index 9e4ea66..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *     Galileo EV96100 board specific pci support.
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * This file was derived from Carsten Langgaard's
- * arch/mips/mips-boards/generic/pci.c
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, 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 as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/delay.h>
-#include <asm/gt64120.h>
-#include <asm/galileo-boards/ev96100.h>
-
-#define PCI_ACCESS_READ  0
-#define PCI_ACCESS_WRITE 1
-
-static int static gt96100_config_access(unsigned char access_type,
-       struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
-{
-       unsigned char bus = bus->number;
-       u32 intr;
-
-       /*
-        * Because of a bug in the galileo (for slot 31).
-        */
-       if (bus == 0 && devfn >= PCI_DEVFN(31, 0))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       /* Clear cause register bits */
-       GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
-                                    GT_INTRCAUSE_TARABORT0_BIT));
-
-       /* Setup address */
-       GT_WRITE(GT_PCI0_CFGADDR_OFS,
-                (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) |
-                (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) |
-                ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) |
-                GT_PCI0_CFGADDR_CONFIGEN_BIT);
-       udelay(2);
-
-
-       if (access_type == PCI_ACCESS_WRITE) {
-               if (devfn != 0)
-                       *data = le32_to_cpu(*data);
-               GT_WRITE(GT_PCI0_CFGDATA_OFS, *data);
-       } else {
-               *data = GT_READ(GT_PCI0_CFGDATA_OFS);
-               if (devfn != 0)
-                       *data = le32_to_cpu(*data);
-       }
-
-       udelay(2);
-
-       /* Check for master or target abort */
-       intr = GT_READ(GT_INTRCAUSE_OFS);
-
-       if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) {
-               /* Error occured */
-
-               /* Clear bits */
-               GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT |
-                                            GT_INTRCAUSE_TARABORT0_BIT));
-               return -1;
-       }
-       return 0;
-}
-
-/*
- * We can't address 8 and 16 bit words directly.  Instead we have to
- * read/write a 32bit word and mask/modify the data we actually want.
- */
-static int gt96100_pcibios_read(struct pci_bus *bus, unsigned int devfn,
-       int where, int size, u32 * val)
-{
-       u32 data = 0;
-
-       if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
-       switch (size) {
-       case 1:
-               *val = (data >> ((where & 3) << 3)) & 0xff;
-               break;
-
-       case 2:
-               *val = (data >> ((where & 3) << 3)) & 0xffff;
-               break;
-
-       case 4:
-               *val = data;
-               break;
-       }
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int gt96100_pcibios_write(struct pci_bus *bus, unsigned int devfn,
-       int where, int size, u32 val)
-{
-       u32 data = 0;
-
-       switch (size) {
-       case 1:
-               if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
-                       return -1;
-
-               data = (data & ~(0xff << ((where & 3) << 3))) |
-                      (val << ((where & 3) << 3));
-
-               if (gt96100_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
-                       return -1;
-
-               return PCIBIOS_SUCCESSFUL;
-
-       case 2:
-               if (gt96100_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
-                       return -1;
-
-               data = (data & ~(0xffff << ((where & 3) << 3))) |
-                      (val << ((where & 3) << 3));
-
-               if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data))
-                       return -1;
-
-
-               return PCIBIOS_SUCCESSFUL;
-
-       case 4:
-               if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &val))
-                       return -1;
-
-               return PCIBIOS_SUCCESSFUL;
-       }
-}
-
-struct pci_ops gt96100_pci_ops = {
-       .read   = gt96100_pcibios_read,
-       .write  = gt96100_pcibios_write
-};
diff --git a/arch/mips/pci/pci-ev96100.c b/arch/mips/pci/pci-ev96100.c
deleted file mode 100644 (file)
index f9457ea..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             ppopov@mvista.com or source@mvista.com
- *
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-static struct resource pci_io_resource = {
-       .name   = "io pci IO space",
-       .start  = 0x10000000,
-       .end    = 0x11ffffff,
-       .flags  = IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
-       .name   = "ext pci memory space",
-       .start  = 0x12000000,
-       .end    = 0x13ffffff,
-       .flags  = IORESOURCE_MEM
-};
-
-extern struct pci_ops gt96100_pci_ops;
-
-struct pci_controller ev96100_controller = {
-       .pci_ops        = &gt96100_pci_ops,
-       .io_resource    = &pci_io_resource,
-       .mem_resource   = &pci_mem_resource,
-};
-
-static void ev96100_pci_init(void)
-{
-       register_pci_controller(&ev96100_controller);
-}
-
-arch_initcall(ev96100_pci_init);
index 80eb9af9ecdffb3c7ec0ab883903a6ac082f05aa..405ce0152739eee2547090c60bf6f35f7ee6ad71 100644 (file)
@@ -16,8 +16,6 @@
 #include <asm/sn/intr.h>
 #include <asm/sn/sn0/hub.h>
 
-extern unsigned int allocate_irqno(void);
-
 /*
  * Max #PCI busses we can handle; ie, max #PCI bridges.
  */
index ed325f0ab28a48be80b366feaa0317c3b0b4f496..a0222fa4416cb62537302e01c4b5ed6a3436d491 100644 (file)
@@ -469,21 +469,6 @@ void bcm1480_kgdb_interrupt(struct pt_regs *regs)
 
 #endif         /* CONFIG_KGDB */
 
-static inline int dclz(unsigned long long x)
-{
-       int lz;
-
-       __asm__ (
-       "       .set    push                                            \n"
-       "       .set    mips64                                          \n"
-       "       dclz    %0, %1                                          \n"
-       "       .set    pop                                             \n"
-       : "=r" (lz)
-       : "r" (x));
-
-       return lz;
-}
-
 extern void bcm1480_timer_interrupt(struct pt_regs *regs);
 extern void bcm1480_mailbox_interrupt(struct pt_regs *regs);
 extern void bcm1480_kgdb_interrupt(struct pt_regs *regs);
@@ -536,9 +521,9 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 
                if (mask_h) {
                        if (mask_h ^ 1)
-                               do_IRQ(63 - dclz(mask_h), regs);
+                               do_IRQ(fls64(mask_h) - 1, regs);
                        else
-                               do_IRQ(127 - dclz(mask_l), regs);
+                               do_IRQ(63 + fls64(mask_l), regs);
                }
        }
 }
index 1de71adec6c665bebb1e47970bed5ae40ad85a93..a451b4c7732d9baae2127529c74f974cf2154278 100644 (file)
@@ -419,21 +419,6 @@ static void sb1250_kgdb_interrupt(struct pt_regs *regs)
 
 #endif         /* CONFIG_KGDB */
 
-static inline int dclz(unsigned long long x)
-{
-       int lz;
-
-       __asm__ (
-       "       .set    push                                            \n"
-       "       .set    mips64                                          \n"
-       "       dclz    %0, %1                                          \n"
-       "       .set    pop                                             \n"
-       : "=r" (lz)
-       : "r" (x));
-
-       return lz;
-}
-
 extern void sb1250_timer_interrupt(struct pt_regs *regs);
 extern void sb1250_mailbox_interrupt(struct pt_regs *regs);
 extern void sb1250_kgdb_interrupt(struct pt_regs *regs);
@@ -490,6 +475,6 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
                mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
                                              R_IMR_INTERRUPT_STATUS_BASE)));
                if (mask)
-                       do_IRQ(63 - dclz(mask), regs);
+                       do_IRQ(fls64(mask) - 1, regs);
        }
 }
index de1ef2fa1a206f2ba7031c66a304f534852371fb..a0dd1b0ee4838fc1b6f6b870354d67886c171fbe 100644 (file)
@@ -731,11 +731,10 @@ config ARCH_SPARSEMEM_DEFAULT
        def_bool y
        depends on SMP && PPC_PSERIES
 
-source "mm/Kconfig"
-
-config HAVE_ARCH_EARLY_PFN_TO_NID
+config ARCH_POPULATES_NODE_MAP
        def_bool y
-       depends on NEED_MULTIPLE_NODES
+
+source "mm/Kconfig"
 
 config ARCH_MEMORY_PROBE
        def_bool y
index 2e292863e982acac45b743248300d2820d73cbb7..5e391fc253407fcfa8b712363d74d46bb99ee7c5 100644 (file)
@@ -740,7 +740,7 @@ asmlinkage long compat_sys_umask(u32 mask)
        return sys_umask((int)mask);
 }
 
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
 struct __sysctl_args32 {
        u32 name;
        int nlen;
index eebd8b83a6b05243f3633bbe4578b2a0e6db0355..16fe027bbc12ffb873222dbbdc170d474028ca91 100644 (file)
@@ -256,20 +256,22 @@ void __init do_init_bootmem(void)
 
        boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
 
+       /* Add active regions with valid PFNs */
+       for (i = 0; i < lmb.memory.cnt; i++) {
+               unsigned long start_pfn, end_pfn;
+               start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
+               end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
+               add_active_range(0, start_pfn, end_pfn);
+       }
+
        /* Add all physical memory to the bootmem map, mark each area
         * present.
         */
-       for (i = 0; i < lmb.memory.cnt; i++) {
-               unsigned long base = lmb.memory.region[i].base;
-               unsigned long size = lmb_size_bytes(&lmb.memory, i);
 #ifdef CONFIG_HIGHMEM
-               if (base >= total_lowmem)
-                       continue;
-               if (base + size > total_lowmem)
-                       size = total_lowmem - base;
+       free_bootmem_with_active_regions(0, total_lowmem >> PAGE_SHIFT);
+#else
+       free_bootmem_with_active_regions(0, max_pfn);
 #endif
-               free_bootmem(base, size);
-       }
 
        /* reserve the sections we're already using */
        for (i = 0; i < lmb.reserved.cnt; i++)
@@ -277,9 +279,8 @@ void __init do_init_bootmem(void)
                                lmb_size_bytes(&lmb.reserved, i));
 
        /* XXX need to clip this if using highmem? */
-       for (i = 0; i < lmb.memory.cnt; i++)
-               memory_present(0, lmb_start_pfn(&lmb.memory, i),
-                              lmb_end_pfn(&lmb.memory, i));
+       sparse_memory_present_with_active_regions(0);
+
        init_bootmem_done = 1;
 }
 
@@ -288,10 +289,9 @@ void __init do_init_bootmem(void)
  */
 void __init paging_init(void)
 {
-       unsigned long zones_size[MAX_NR_ZONES];
-       unsigned long zholes_size[MAX_NR_ZONES];
        unsigned long total_ram = lmb_phys_mem_size();
        unsigned long top_of_ram = lmb_end_of_DRAM();
+       unsigned long max_zone_pfns[MAX_NR_ZONES];
 
 #ifdef CONFIG_HIGHMEM
        map_page(PKMAP_BASE, 0, 0);     /* XXX gross */
@@ -307,26 +307,13 @@ void __init paging_init(void)
               top_of_ram, total_ram);
        printk(KERN_DEBUG "Memory hole size: %ldMB\n",
               (top_of_ram - total_ram) >> 20);
-       /*
-        * All pages are DMA-able so we put them all in the DMA zone.
-        */
-       memset(zones_size, 0, sizeof(zones_size));
-       memset(zholes_size, 0, sizeof(zholes_size));
-
-       zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
-       zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
-
 #ifdef CONFIG_HIGHMEM
-       zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
-       zones_size[ZONE_HIGHMEM] = (total_memory - total_lowmem) >> PAGE_SHIFT;
-       zholes_size[ZONE_HIGHMEM] = (top_of_ram - total_ram) >> PAGE_SHIFT;
+       max_zone_pfns[0] = total_lowmem >> PAGE_SHIFT;
+       max_zone_pfns[1] = top_of_ram >> PAGE_SHIFT;
 #else
-       zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
-       zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT;
-#endif /* CONFIG_HIGHMEM */
-
-       free_area_init_node(0, NODE_DATA(0), zones_size,
-                           __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
+       max_zone_pfns[0] = top_of_ram >> PAGE_SHIFT;
+#endif
+       free_area_init_nodes(max_zone_pfns);
 }
 #endif /* ! CONFIG_NEED_MULTIPLE_NODES */
 
index 6c0f1c7d83e502bf86bb14b567c91d09125a6a3e..43c272075e1ae8408baa35c8e78a2d831e24312c 100644 (file)
@@ -39,96 +39,6 @@ static bootmem_data_t __initdata plat_node_bdata[MAX_NUMNODES];
 static int min_common_depth;
 static int n_mem_addr_cells, n_mem_size_cells;
 
-/*
- * We need somewhere to store start/end/node for each region until we have
- * allocated the real node_data structures.
- */
-#define MAX_REGIONS    (MAX_LMB_REGIONS*2)
-static struct {
-       unsigned long start_pfn;
-       unsigned long end_pfn;
-       int nid;
-} init_node_data[MAX_REGIONS] __initdata;
-
-int __init early_pfn_to_nid(unsigned long pfn)
-{
-       unsigned int i;
-
-       for (i = 0; init_node_data[i].end_pfn; i++) {
-               unsigned long start_pfn = init_node_data[i].start_pfn;
-               unsigned long end_pfn = init_node_data[i].end_pfn;
-
-               if ((start_pfn <= pfn) && (pfn < end_pfn))
-                       return init_node_data[i].nid;
-       }
-
-       return -1;
-}
-
-void __init add_region(unsigned int nid, unsigned long start_pfn,
-                      unsigned long pages)
-{
-       unsigned int i;
-
-       dbg("add_region nid %d start_pfn 0x%lx pages 0x%lx\n",
-               nid, start_pfn, pages);
-
-       for (i = 0; init_node_data[i].end_pfn; i++) {
-               if (init_node_data[i].nid != nid)
-                       continue;
-               if (init_node_data[i].end_pfn == start_pfn) {
-                       init_node_data[i].end_pfn += pages;
-                       return;
-               }
-               if (init_node_data[i].start_pfn == (start_pfn + pages)) {
-                       init_node_data[i].start_pfn -= pages;
-                       return;
-               }
-       }
-
-       /*
-        * Leave last entry NULL so we dont iterate off the end (we use
-        * entry.end_pfn to terminate the walk).
-        */
-       if (i >= (MAX_REGIONS - 1)) {
-               printk(KERN_ERR "WARNING: too many memory regions in "
-                               "numa code, truncating\n");
-               return;
-       }
-
-       init_node_data[i].start_pfn = start_pfn;
-       init_node_data[i].end_pfn = start_pfn + pages;
-       init_node_data[i].nid = nid;
-}
-
-/* We assume init_node_data has no overlapping regions */
-void __init get_region(unsigned int nid, unsigned long *start_pfn,
-                      unsigned long *end_pfn, unsigned long *pages_present)
-{
-       unsigned int i;
-
-       *start_pfn = -1UL;
-       *end_pfn = *pages_present = 0;
-
-       for (i = 0; init_node_data[i].end_pfn; i++) {
-               if (init_node_data[i].nid != nid)
-                       continue;
-
-               *pages_present += init_node_data[i].end_pfn -
-                       init_node_data[i].start_pfn;
-
-               if (init_node_data[i].start_pfn < *start_pfn)
-                       *start_pfn = init_node_data[i].start_pfn;
-
-               if (init_node_data[i].end_pfn > *end_pfn)
-                       *end_pfn = init_node_data[i].end_pfn;
-       }
-
-       /* We didnt find a matching region, return start/end as 0 */
-       if (*start_pfn == -1UL)
-               *start_pfn = 0;
-}
-
 static void __cpuinit map_cpu_to_node(int cpu, int node)
 {
        numa_cpu_lookup_table[cpu] = node;
@@ -468,8 +378,8 @@ new_range:
                                continue;
                }
 
-               add_region(nid, start >> PAGE_SHIFT,
-                          size >> PAGE_SHIFT);
+               add_active_range(nid, start >> PAGE_SHIFT,
+                               (start >> PAGE_SHIFT) + (size >> PAGE_SHIFT));
 
                if (--ranges)
                        goto new_range;
@@ -482,6 +392,7 @@ static void __init setup_nonnuma(void)
 {
        unsigned long top_of_ram = lmb_end_of_DRAM();
        unsigned long total_ram = lmb_phys_mem_size();
+       unsigned long start_pfn, end_pfn;
        unsigned int i;
 
        printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",
@@ -489,9 +400,11 @@ static void __init setup_nonnuma(void)
        printk(KERN_DEBUG "Memory hole size: %ldMB\n",
               (top_of_ram - total_ram) >> 20);
 
-       for (i = 0; i < lmb.memory.cnt; ++i)
-               add_region(0, lmb.memory.region[i].base >> PAGE_SHIFT,
-                          lmb_size_pages(&lmb.memory, i));
+       for (i = 0; i < lmb.memory.cnt; ++i) {
+               start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT;
+               end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i);
+               add_active_range(0, start_pfn, end_pfn);
+       }
        node_set_online(0);
 }
 
@@ -630,11 +543,11 @@ void __init do_init_bootmem(void)
                          (void *)(unsigned long)boot_cpuid);
 
        for_each_online_node(nid) {
-               unsigned long start_pfn, end_pfn, pages_present;
+               unsigned long start_pfn, end_pfn;
                unsigned long bootmem_paddr;
                unsigned long bootmap_pages;
 
-               get_region(nid, &start_pfn, &end_pfn, &pages_present);
+               get_pfn_range_for_nid(nid, &start_pfn, &end_pfn);
 
                /* Allocate the node structure node local if possible */
                NODE_DATA(nid) = careful_allocation(nid,
@@ -667,19 +580,7 @@ void __init do_init_bootmem(void)
                init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,
                                  start_pfn, end_pfn);
 
-               /* Add free regions on this node */
-               for (i = 0; init_node_data[i].end_pfn; i++) {
-                       unsigned long start, end;
-
-                       if (init_node_data[i].nid != nid)
-                               continue;
-
-                       start = init_node_data[i].start_pfn << PAGE_SHIFT;
-                       end = init_node_data[i].end_pfn << PAGE_SHIFT;
-
-                       dbg("free_bootmem %lx %lx\n", start, end - start);
-                       free_bootmem_node(NODE_DATA(nid), start, end - start);
-               }
+               free_bootmem_with_active_regions(nid, end_pfn);
 
                /* Mark reserved regions on this node */
                for (i = 0; i < lmb.reserved.cnt; i++) {
@@ -710,44 +611,16 @@ void __init do_init_bootmem(void)
                        }
                }
 
-               /* Add regions into sparsemem */
-               for (i = 0; init_node_data[i].end_pfn; i++) {
-                       unsigned long start, end;
-
-                       if (init_node_data[i].nid != nid)
-                               continue;
-
-                       start = init_node_data[i].start_pfn;
-                       end = init_node_data[i].end_pfn;
-
-                       memory_present(nid, start, end);
-               }
+               sparse_memory_present_with_active_regions(nid);
        }
 }
 
 void __init paging_init(void)
 {
-       unsigned long zones_size[MAX_NR_ZONES];
-       unsigned long zholes_size[MAX_NR_ZONES];
-       int nid;
-
-       memset(zones_size, 0, sizeof(zones_size));
-       memset(zholes_size, 0, sizeof(zholes_size));
-
-       for_each_online_node(nid) {
-               unsigned long start_pfn, end_pfn, pages_present;
-
-               get_region(nid, &start_pfn, &end_pfn, &pages_present);
-
-               zones_size[ZONE_DMA] = end_pfn - start_pfn;
-               zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] - pages_present;
-
-               dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid,
-                   zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]);
-
-               free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn,
-                                   zholes_size);
-       }
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = {
+                               lmb_end_of_DRAM() >> PAGE_SHIFT
+       };
+       free_area_init_nodes(max_zone_pfns);
 }
 
 static int __init early_numa(char *p)
index 7b4572805db9973388267c3ae9d1cea61fea0ed7..3950ddccb2c8531d451c8a188b86ae95371ec797 100644 (file)
@@ -82,7 +82,6 @@ spufs_new_inode(struct super_block *sb, int mode)
        inode->i_mode = mode;
        inode->i_uid = current->fsuid;
        inode->i_gid = current->fsgid;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 out:
@@ -120,7 +119,7 @@ spufs_new_file(struct super_block *sb, struct dentry *dentry,
        ret = 0;
        inode->i_op = &spufs_file_iops;
        inode->i_fop = fops;
-       inode->u.generic_ip = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
+       inode->i_private = SPUFS_I(inode)->i_ctx = get_spu_context(ctx);
        d_add(dentry, inode);
 out:
        return ret;
index 641e6511cf0660efee29227787e3a029466cdbda..446e17d162a545e004c18779e61e8c5b4e398414 100644 (file)
@@ -85,7 +85,7 @@ static int hcall_inst_seq_open(struct inode *inode, struct file *file)
 
        rc = seq_open(file, &hcall_inst_seq_ops);
        seq = file->private_data;
-       seq->private = file->f_dentry->d_inode->u.generic_ip;
+       seq->private = file->f_dentry->d_inode->i_private;
 
        return rc;
 }
index b604926401f501575c1832f23ea2b449c86504e5..723972bb5bd9c692d157a9e79bec10cba9a80ae4 100644 (file)
@@ -339,7 +339,7 @@ static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
        for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
             pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
                u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
-               if (id == PCI_CAP_ID_HT_IRQCONF) {
+               if (id == PCI_CAP_ID_HT) {
                        id = readb(devbase + pos + 3);
                        if (id == 0x80)
                                break;
index 8fa10cf661a80191fc0912463591ff6579d1663c..fdd9e7b6624479e712031974d0029fbde452e4a6 100644 (file)
@@ -953,6 +953,9 @@ config NR_CPUS
 config HIGHMEM
        bool "High memory support"
 
+config ARCH_POPULATES_NODE_MAP
+       def_bool y
+
 source kernel/Kconfig.hz
 source kernel/Kconfig.preempt
 source "mm/Kconfig"
index 523392d460fa129aecceb4a0c8f5e0f541f0c970..410200046af120236e44fb35d656e57f65ceb0da 100644 (file)
@@ -358,8 +358,8 @@ void __init do_init_bootmem(void)
  */
 void __init paging_init(void)
 {
-       unsigned long zones_size[MAX_NR_ZONES], i;
-
+       unsigned long start_pfn, end_pfn;
+       unsigned long max_zone_pfns[MAX_NR_ZONES];
 #ifdef CONFIG_HIGHMEM
        map_page(PKMAP_BASE, 0, 0);     /* XXX gross */
        pkmap_page_table = pte_offset_kernel(pmd_offset(pgd_offset_k
@@ -369,19 +369,18 @@ void __init paging_init(void)
                        (KMAP_FIX_BEGIN), KMAP_FIX_BEGIN), KMAP_FIX_BEGIN);
        kmap_prot = PAGE_KERNEL;
 #endif /* CONFIG_HIGHMEM */
-
-       /*
-        * All pages are DMA-able so we put them all in the DMA zone.
-        */
-       zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
-       for (i = 1; i < MAX_NR_ZONES; i++)
-               zones_size[i] = 0;
+       /* All pages are DMA-able so we put them all in the DMA zone. */
+       start_pfn = __pa(PAGE_OFFSET) >> PAGE_SHIFT;
+       end_pfn = start_pfn + (total_memory >> PAGE_SHIFT);
+       add_active_range(0, start_pfn, end_pfn);
 
 #ifdef CONFIG_HIGHMEM
-       zones_size[ZONE_HIGHMEM] = (total_memory - total_lowmem) >> PAGE_SHIFT;
+       max_zone_pfns[0] = total_lowmem >> PAGE_SHIFT;
+       max_zone_pfns[1] = total_memory >> PAGE_SHIFT;
+#else
+       max_zone_pfns[0] = total_memory >> PAGE_SHIFT;
 #endif /* CONFIG_HIGHMEM */
-
-       free_area_init(zones_size);
+       free_area_init_nodes(max_zone_pfns);
 }
 
 void __init mem_init(void)
index bdade5f2e325e6b43a1bef2dc7b0833491ccb644..813fc21358f9764cc2ae6a34a17d5edcd60c265c 100644 (file)
@@ -91,7 +91,6 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
                ret->i_mode = mode;
                ret->i_uid = hypfs_info->uid;
                ret->i_gid = hypfs_info->gid;
-               ret->i_blksize = PAGE_CACHE_SIZE;
                ret->i_blocks = 0;
                ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
                if (mode & S_IFDIR)
@@ -104,13 +103,13 @@ static struct inode *hypfs_make_inode(struct super_block *sb, int mode)
 
 static void hypfs_drop_inode(struct inode *inode)
 {
-       kfree(inode->u.generic_ip);
+       kfree(inode->i_private);
        generic_delete_inode(inode);
 }
 
 static int hypfs_open(struct inode *inode, struct file *filp)
 {
-       char *data = filp->f_dentry->d_inode->u.generic_ip;
+       char *data = filp->f_dentry->d_inode->i_private;
        struct hypfs_sb_info *fs_info;
 
        if (filp->f_mode & FMODE_WRITE) {
@@ -352,7 +351,7 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
                parent->d_inode->i_nlink++;
        } else
                BUG();
-       inode->u.generic_ip = data;
+       inode->i_private = data;
        d_instantiate(dentry, inode);
        dget(dentry);
        return dentry;
index 785c9f70ac980b328360560ffa8858191a60c382..91b2884fa5c4c77ff6909d45631618e1dceec8be 100644 (file)
@@ -708,7 +708,7 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd,
        return ret;
 }
 
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
 struct __sysctl_args32 {
        u32 name;
        int nlen;
index 7ba20922a535d848a1de8316676d57cb5a9eb469..43f3d0c7e132372f05279073a6b60f869d2ef323 100644 (file)
@@ -603,7 +603,7 @@ debug_open(struct inode *inode, struct file *file)
        debug_info_t *debug_info, *debug_info_snapshot;
 
        down(&debug_lock);
-       debug_info = (struct debug_info*)file->f_dentry->d_inode->u.generic_ip;
+       debug_info = file->f_dentry->d_inode->i_private;
        /* find debug view */
        for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
                if (!debug_info->views[i])
index de83f38288d08b1116f11a5ccfb6836af045f338..d9428a0fc8fb9ee3011f90f35f74a3be97bee70e 100644 (file)
@@ -59,9 +59,7 @@ static inline unsigned long save_context_stack(struct stack_trace *trace,
        }
 }
 
-void save_stack_trace(struct stack_trace *trace,
-                     struct task_struct *task, int all_contexts,
-                     unsigned int skip)
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
 {
        register unsigned long sp asm ("15");
        unsigned long orig_sp;
@@ -69,22 +67,23 @@ void save_stack_trace(struct stack_trace *trace,
        sp &= PSW_ADDR_INSN;
        orig_sp = sp;
 
-       sp = save_context_stack(trace, &skip, sp,
+       sp = save_context_stack(trace, &trace->skip, sp,
                                S390_lowcore.panic_stack - PAGE_SIZE,
                                S390_lowcore.panic_stack);
-       if ((sp != orig_sp) && !all_contexts)
+       if ((sp != orig_sp) && !trace->all_contexts)
                return;
-       sp = save_context_stack(trace, &skip, sp,
+       sp = save_context_stack(trace, &trace->skip, sp,
                                S390_lowcore.async_stack - ASYNC_SIZE,
                                S390_lowcore.async_stack);
-       if ((sp != orig_sp) && !all_contexts)
+       if ((sp != orig_sp) && !trace->all_contexts)
                return;
        if (task)
-               save_context_stack(trace, &skip, sp,
+               save_context_stack(trace, &trace->skip, sp,
                                   (unsigned long) task_stack_page(task),
                                   (unsigned long) task_stack_page(task) + THREAD_SIZE);
        else
-               save_context_stack(trace, &skip, sp, S390_lowcore.thread_info,
+               save_context_stack(trace, &trace->skip, sp,
+                                  S390_lowcore.thread_info,
                                   S390_lowcore.thread_info + THREAD_SIZE);
        return;
 }
index 1a0db1d4c952fe31e91729e3489e985aee32d31d..1cc5c9b27bfdeae32671c58e61263d929c92f6e2 100644 (file)
@@ -8,6 +8,7 @@ mainmenu "Linux/SuperH Kernel Configuration"
 config SUPERH
        bool
        default y
+       select EMBEDDED
        help
          The SuperH is a RISC processor targeted for use in embedded systems
          and consumer electronics; it was also used in the Sega Dreamcast
@@ -51,18 +52,23 @@ source "init/Kconfig"
 
 menu "System type"
 
+config SOLUTION_ENGINE
+       bool
+
 choice
        prompt "SuperH system type"
        default SH_UNKNOWN
 
 config SH_SOLUTION_ENGINE
        bool "SolutionEngine"
+       select SOLUTION_ENGINE
        help
          Select SolutionEngine if configuring for a Hitachi SH7709
          or SH7750 evaluation board.
 
 config SH_7751_SOLUTION_ENGINE
        bool "SolutionEngine7751"
+       select SOLUTION_ENGINE
        select CPU_SUBTYPE_SH7751
        help
          Select 7751 SolutionEngine if configuring for a Hitachi SH7751
@@ -70,17 +76,27 @@ config SH_7751_SOLUTION_ENGINE
 
 config SH_7300_SOLUTION_ENGINE
        bool "SolutionEngine7300"
+       select SOLUTION_ENGINE
        select CPU_SUBTYPE_SH7300
        help
-         Select 7300 SolutionEngine if configuring for a Hitachi SH7300(SH-Mobile V)
-         evaluation board.
+         Select 7300 SolutionEngine if configuring for a Hitachi
+         SH7300(SH-Mobile V) evaluation board.
+
+config SH_7343_SOLUTION_ENGINE
+       bool "SolutionEngine7343"
+       select SOLUTION_ENGINE
+       select CPU_SUBTYPE_SH7343
+       help
+         Select 7343 SolutionEngine if configuring for a Hitachi
+         SH7343 (SH-Mobile 3AS) evaluation board.
 
 config SH_73180_SOLUTION_ENGINE
        bool "SolutionEngine73180"
-       select CPU_SUBTYPE_SH73180
-       help
-         Select 73180 SolutionEngine if configuring for a Hitachi SH73180(SH-Mobile 3)
-         evaluation board.
+       select SOLUTION_ENGINE
+       select CPU_SUBTYPE_SH73180
+       help
+         Select 73180 SolutionEngine if configuring for a Hitachi
+         SH73180(SH-Mobile 3) evaluation board.
 
 config SH_7751_SYSTEMH
        bool "SystemH7751R"
@@ -89,12 +105,6 @@ config SH_7751_SYSTEMH
          Select SystemH if you are configuring for a Renesas SystemH
          7751R evaluation board.
 
-config SH_STB1_HARP
-       bool "STB1_Harp"
-
-config SH_STB1_OVERDRIVE
-       bool "STB1_Overdrive"
-
 config SH_HP6XX
        bool "HP6XX"
        help
@@ -102,19 +112,6 @@ config SH_HP6XX
          More information (hardware only) at
          <http://www.hp.com/jornada/>.
 
-config SH_CQREEK
-       bool "CqREEK"
-       help
-         Select CqREEK if configuring for a CqREEK SH7708 or SH7750.
-         More information at
-         <http://sources.redhat.com/ecos/hardware.html#SuperH>.
-
-config SH_DMIDA
-       bool "DMIDA"
-       help
-         Select DMIDA if configuring for a DataMyte 4000 Industrial
-         Digital Assistant. More information at <http://www.dmida.com/>.
-
 config SH_EC3104
        bool "EC3104"
        help
@@ -136,25 +133,9 @@ config SH_DREAMCAST
          <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
          Dreamcast project is at <http://linuxdc.sourceforge.net/>.
 
-config SH_CAT68701
-       bool "CAT68701"
-
 config SH_BIGSUR
        bool "BigSur"
 
-config SH_SH2000
-       bool "SH2000"
-       select CPU_SUBTYPE_SH7709
-       help
-         SH-2000 is a single-board computer based around SH7709A chip
-         intended for embedded applications.
-         It has an Ethernet interface (CS8900A), direct connected
-         Compact Flash socket, three serial ports and PC-104 bus.
-         More information at <http://sh2000.sh-linux.org>.
-
-config SH_ADX
-       bool "ADX"
-
 config SH_MPC1211
        bool "Interface MPC1211"
        help
@@ -184,6 +165,13 @@ config SH_HS7751RVOIP
          Select HS7751RVOIP if configuring for a Renesas Technology
          Sales VoIP board.
 
+config SH_7710VOIPGW
+       bool "SH7710-VOIP-GW"
+       select CPU_SUBTYPE_SH7710
+       help
+         Select this option to build a kernel for the SH7710 based
+         VOIP GW.
+
 config SH_RTS7751R2D
        bool "RTS7751R2D"
        select CPU_SUBTYPE_SH7751R
@@ -222,6 +210,12 @@ config SH_TITAN
          Select Titan if you are configuring for a Nimble Microsystems
          NetEngine NP51R.
 
+config SH_SHMIN
+       bool "SHMIN"
+       select CPU_SUBTYPE_SH7706
+       help
+         Select SHMIN if configureing for the SHMIN board
+
 config SH_UNKNOWN
        bool "BareCPU"
        help
@@ -238,35 +232,9 @@ endchoice
 
 source "arch/sh/mm/Kconfig"
 
-config MEMORY_START
-       hex "Physical memory start address"
-       default "0x08000000"
-       ---help---
-         Computers built with Hitachi SuperH processors always
-         map the ROM starting at address zero.  But the processor
-         does not specify the range that RAM takes.
-
-         The physical memory (RAM) start address will be automatically
-         set to 08000000. Other platforms, such as the Solution Engine
-         boards typically map RAM at 0C000000.
-
-         Tweak this only when porting to a new machine which does not
-         already have a defconfig. Changing it from the known correct
-         value on any of the known systems will only lead to disaster.
-
-config MEMORY_SIZE
-       hex "Physical memory size"
-       default "0x00400000"
-       help
-         This sets the default memory size assumed by your SH kernel. It can
-         be overridden as normal by the 'mem=' argument on the kernel command
-         line. If unsure, consult your board specifications or just leave it
-         as 0x00400000 which was the default value before this became
-         configurable.
-
 config CF_ENABLER
        bool "Compact Flash Enabler support"
-       depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 || SH_SH03
+       depends on SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_SH03
        ---help---
          Compact Flash is a small, removable mass storage device introduced
          in 1994 originally as a PCMCIA device.  If you say `Y' here, you
@@ -294,7 +262,7 @@ config CF_AREA5
          - "Area5" if CompactFlash is connected to Area 5 (0x14000000)
          - "Area6" if it is connected to Area 6 (0x18000000)
 
-         "Area6" will work for most boards. For ADX, select "Area5".
+         "Area6" will work for most boards.
 
 config CF_AREA6
        bool "Area6"
@@ -316,19 +284,6 @@ config CPU_LITTLE_ENDIAN
          endian byte order. These modes require different kernels. Say Y if
          your machine is little endian, N if it's a big endian machine.
 
-# The SH7750 RTC module is disabled in the Dreamcast
-config SH_RTC
-       bool
-       depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && \
-                  !SH_73180_SOLUTION_ENGINE && !SH_LANDISK && \
-                  !SH_R7780RP
-       default y
-       help
-         Selecting this option will allow the Linux kernel to emulate
-         PC's RTC.
-
-         If unsure, say N.
-
 config SH_FPU
        bool "FPU support"
        depends on !CPU_SH3
@@ -339,14 +294,22 @@ config SH_FPU
 
          This option must be set in order to enable the FPU.
 
+config SH_FPU_EMU
+       bool "FPU emulation support"
+       depends on !SH_FPU && EXPERIMENTAL
+       default n
+       help
+         Selecting this option will enable support for software FPU emulation.
+         Most SH-3 users will want to say Y here, whereas most SH-4 users will
+         want to say N.
+
 config SH_DSP
        bool "DSP support"
-       depends on !CPU_SH4
-       default y
+       default y if SH4AL_DSP || !CPU_SH4
+       default n
        help
          Selecting this option will enable support for SH processors that
-         have DSP units (ie, SH2-DSP and SH3-DSP). It is safe to say Y here
-         by default, as the existance of the DSP will be probed at runtime.
+         have DSP units (ie, SH2-DSP, SH3-DSP, and SH4AL-DSP).
 
          This option must be set in order to enable the DSP.
 
@@ -373,6 +336,9 @@ config CPU_HAS_INTEVT
 config CPU_HAS_PINT_IRQ
        bool
 
+config CPU_HAS_MASKREG_IRQ
+       bool
+
 config CPU_HAS_INTC2_IRQ
        bool
 
@@ -400,16 +366,19 @@ config SH_TMU
 
 endmenu
 
-#source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
+source "arch/sh/boards/renesas/hs7751rvoip/Kconfig"
+
+source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
 
-#source "arch/sh/boards/renesas/rts7751r2d/Kconfig"
+source "arch/sh/boards/renesas/r7780rp/Kconfig"
 
 config SH_PCLK_FREQ
        int "Peripheral clock frequency (in Hz)"
        default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780
        default "60000000" if CPU_SUBTYPE_SH7751
-       default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7760
-       default "27000000" if CPU_SUBTYPE_SH73180
+       default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || \
+                             CPU_SUBTYPE_SH7760
+       default "27000000" if CPU_SUBTYPE_SH73180 || CPU_SUBTYPE_SH7343
        default "66000000" if CPU_SUBTYPE_SH4_202
        help
          This option is used to specify the peripheral clock frequency.
@@ -440,10 +409,8 @@ source "arch/sh/cchips/Kconfig"
 
 config HEARTBEAT
        bool "Heartbeat LED"
-       depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || \
-                  SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || \
-                  SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || \
-                  SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || \
+       depends on SH_MPC1211 || SH_SH03 || \
+                  SH_BIGSUR || SOLUTION_ENGINE || \
                   SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK
        help
          Use the power-on LED on your machine as a load meter.  The exact
@@ -459,6 +426,8 @@ config ISA_DMA_API
 
 menu "Kernel features"
 
+source kernel/Kconfig.hz
+
 config KEXEC
        bool "kexec system call (EXPERIMENTAL)"
        depends on EXPERIMENTAL
@@ -476,10 +445,6 @@ config KEXEC
          support.  As of this writing the exact hardware interface is
          strongly in flux, so no good recommendation can be made.
 
-config PREEMPT
-       bool "Preemptible Kernel (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
-
 config SMP
        bool "Symmetric multi-processing support"
        ---help---
@@ -515,6 +480,8 @@ config NR_CPUS
          This is purely to save memory - each supported CPU adds
          approximately eight kilobytes to the kernel image.
 
+source "kernel/Kconfig.preempt"
+
 config CPU_HAS_SR_RB
        bool "CPU has SR.RB"
        depends on CPU_SH3 || CPU_SH4
@@ -636,6 +603,16 @@ source "fs/Kconfig.binfmt"
 
 endmenu
 
+menu "Power management options (EXPERIMENTAL)"
+depends on EXPERIMENTAL
+
+source kernel/power/Kconfig
+
+config APM
+       bool "Advanced Power Management Emulation"
+       depends on PM
+endmenu
+
 source "net/Kconfig"
 
 source "drivers/Kconfig"
index 8fb31ab2c02c1fa4031013310f8a07df42291b36..48479e014dac657f3b36dc4252801ed38e61b1b9 100644 (file)
@@ -30,8 +30,35 @@ config EARLY_PRINTK
          when the kernel may crash or hang before the serial console is
          initialised. If unsure, say N.
 
+config DEBUG_STACKOVERFLOW
+       bool "Check for stack overflows"
+       depends on DEBUG_KERNEL
+       help
+         This option will cause messages to be printed if free stack space
+         drops below a certain limit.
+
+config DEBUG_STACK_USAGE
+       bool "Stack utilization instrumentation"
+       depends on DEBUG_KERNEL
+       help
+         Enables the display of the minimum amount of free stack which each
+         task has ever had available in the sysrq-T and sysrq-P debug output.
+
+         This option will slow down process creation somewhat.
+
+config 4KSTACKS
+       bool "Use 4Kb for kernel stacks instead of 8Kb"
+       depends on DEBUG_KERNEL
+       help
+         If you say Y here the kernel will use a 4Kb stacksize for the
+         kernel stack attached to each process/thread. This facilitates
+         running more threads on a system and also reduces the pressure
+         on the VM subsystem for higher order allocations. This option
+         will also use IRQ stacks to compensate for the reduced stackspace.
+
 config KGDB
        bool "Include KGDB kernel debugger"
+       select FRAME_POINTER
        help
          Include in-kernel hooks for kgdb, the Linux kernel source level
          debugger.  See <http://kgdb.sourceforge.net/> for more information.
@@ -112,13 +139,4 @@ endchoice
 
 endmenu
 
-config FRAME_POINTER
-       bool "Compile the kernel with frame pointers"
-       default y if KGDB
-       help
-         If you say Y here the resulting kernel image will be slightly larger
-         and slower, but it will give very useful debugging information.
-         If you don't debug the kernel, you can say N, but we may not be able
-         to solve problems without frame pointers.
-
 endmenu
index e467a450662bee9e6538bd0f1a8be279972f1a70..26d62ff51a64e951b96aa90d1620365f15c7a1a1 100644 (file)
@@ -18,11 +18,13 @@ cflags-y                            := -mb
 cflags-$(CONFIG_CPU_LITTLE_ENDIAN)     := -ml
 
 isa-y                                  := any
+isa-$(CONFIG_SH_DSP)                   := sh
 isa-$(CONFIG_CPU_SH2)                  := sh2
+isa-$(CONFIG_CPU_SH2A)                 := sh2a
 isa-$(CONFIG_CPU_SH3)                  := sh3
 isa-$(CONFIG_CPU_SH4)                  := sh4
 isa-$(CONFIG_CPU_SH4A)                 := sh4a
-isa-$(CONFIG_CPU_SH2A)                 := sh2a
+isa-$(CONFIG_CPU_SH4AL_DSP)            := sh4al
 
 isa-$(CONFIG_SH_DSP)                   := $(isa-y)-dsp
 
@@ -30,9 +32,11 @@ ifndef CONFIG_MMU
 isa-y                  := $(isa-y)-nommu
 endif
 
+ifndef CONFIG_SH_DSP
 ifndef CONFIG_SH_FPU
 isa-y                  := $(isa-y)-nofpu
 endif
+endif
 
 cflags-y       += $(call as-option,-Wa$(comma)-isa=$(isa-y),)
 
@@ -79,24 +83,19 @@ head-y := arch/sh/kernel/head.o arch/sh/kernel/init_task.o
 LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
 
 core-y                         += arch/sh/kernel/ arch/sh/mm/
+core-$(CONFIG_SH_FPU_EMU)      += arch/sh/math-emu/
 
 # Boards
 machdir-$(CONFIG_SH_SOLUTION_ENGINE)           := se/770x
 machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)      := se/7751
 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_STB1_HARP)                 := harp
-machdir-$(CONFIG_SH_STB1_OVERDRIVE)            := overdrive
 machdir-$(CONFIG_SH_HP6XX)                     := hp6xx
-machdir-$(CONFIG_SH_CQREEK)                    := cqreek
-machdir-$(CONFIG_SH_DMIDA)                     := dmida
 machdir-$(CONFIG_SH_EC3104)                    := ec3104
 machdir-$(CONFIG_SH_SATURN)                    := saturn
 machdir-$(CONFIG_SH_DREAMCAST)                 := dreamcast
-machdir-$(CONFIG_SH_CAT68701)                  := cat68701
 machdir-$(CONFIG_SH_BIGSUR)                    := bigsur
-machdir-$(CONFIG_SH_SH2000)                    := sh2000
-machdir-$(CONFIG_SH_ADX)                       := adx
 machdir-$(CONFIG_SH_MPC1211)                   := mpc1211
 machdir-$(CONFIG_SH_SH03)                      := sh03
 machdir-$(CONFIG_SH_SECUREEDGE5410)            := snapgear
@@ -104,16 +103,16 @@ machdir-$(CONFIG_SH_HS7751RVOIP)          := renesas/hs7751rvoip
 machdir-$(CONFIG_SH_RTS7751R2D)                        := renesas/rts7751r2d
 machdir-$(CONFIG_SH_7751_SYSTEMH)              := renesas/systemh
 machdir-$(CONFIG_SH_EDOSK7705)                 := renesas/edosk7705
+machdir-$(CONFIG_SH_R7780RP)                   := renesas/r7780rp
+machdir-$(CONFIG_SH_7710VOIPGW)                        := renesas/sh7710voipgw
 machdir-$(CONFIG_SH_SH4202_MICRODEV)           := superh/microdev
+machdir-$(CONFIG_SH_LANDISK)                   := landisk
+machdir-$(CONFIG_SH_TITAN)                     := titan
+machdir-$(CONFIG_SH_SHMIN)                     := shmin
 machdir-$(CONFIG_SH_UNKNOWN)                   := unknown
 
 incdir-y                       := $(notdir $(machdir-y))
-
-incdir-$(CONFIG_SH_SOLUTION_ENGINE)            := se
-incdir-$(CONFIG_SH_7751_SOLUTION_ENGINE)       := se7751
-incdir-$(CONFIG_SH_7300_SOLUTION_ENGINE)        := se7300
-incdir-$(CONFIG_SH_73180_SOLUTION_ENGINE)      := se73180
-incdir-$(CONFIG_SH_HP600)                      := hp6xx
+incdir-$(CONFIG_SH_HP6XX)                      := hp6xx
 
 ifneq ($(machdir-y),)
 core-y                         += arch/sh/boards/$(machdir-y)/
@@ -137,17 +136,14 @@ boot := arch/sh/boot
 
 CPPFLAGS_vmlinux.lds := -traditional
 
-ifneq ($(KBUILD_SRC),)
 incdir-prefix  := $(srctree)/include/asm-sh/
-else
-incdir-prefix  :=
-endif
 
 #      Update machine arch and proc symlinks if something which affects
 #      them changed.  We use .arch and .mach to indicate when they were
 #      updated last, otherwise make uses the target directory mtime.
 
-include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/auto.conf
+include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) \
+                    include/config/auto.conf FORCE
        @echo '  SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)'
        $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
        $(Q)ln -fsn $(incdir-prefix)$(cpuincdir-y) include/asm-sh/cpu
@@ -157,7 +153,8 @@ include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/auto.conf
 #      don't, just reference the parent directory so the semantics are
 #      kept roughly the same.
 
-include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/auto.conf
+include/asm-sh/.mach: $(wildcard include/config/sh/*.h) \
+                     include/config/auto.conf FORCE
        @echo -n '  SYMLINK include/asm-sh/mach -> '
        $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi
        $(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \
@@ -170,7 +167,7 @@ include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/auto.conf
        fi
        @touch $@
 
-archprepare: maketools include/asm-sh/.cpu include/asm-sh/.mach
+archprepare: include/asm-sh/.cpu include/asm-sh/.mach maketools
 
 PHONY += maketools FORCE
 maketools:  include/linux/version.h FORCE
@@ -191,4 +188,3 @@ CLEAN_FILES += include/asm-sh/machtypes.h
 define archhelp
        @echo '  zImage                    - Compressed kernel image (arch/sh/boot/zImage)'
 endef
-
diff --git a/arch/sh/boards/adx/Makefile b/arch/sh/boards/adx/Makefile
deleted file mode 100644 (file)
index 5b1c531..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for ADX boards
-#
-
-obj-y   := setup.o irq.o irq_maskreq.o
-
diff --git a/arch/sh/boards/adx/irq.c b/arch/sh/boards/adx/irq.c
deleted file mode 100644 (file)
index c6ca409..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * linux/arch/sh/boards/adx/irq.c
- *
- * Copyright (C) 2001 A&D Co., Ltd.
- *
- * I/O routine and setup routines for A&D ADX Board
- *
- * 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 <asm/irq.h>
-
-void init_adx_IRQ(void)
-{
-        int i;
-
-/*      printk("init_adx_IRQ()\n");*/
-        /* setup irq_mask_register */
-        irq_mask_register = (unsigned short *)0xa6000008;
-
-        /* cover all external interrupt area by maskreg_irq_type
-         * (Actually, irq15 doesn't exist)
-         */
-        for (i = 0; i < 16; i++) {
-                make_maskreg_irq(i);
-                disable_irq(i);
-        }
-}
diff --git a/arch/sh/boards/adx/setup.c b/arch/sh/boards/adx/setup.c
deleted file mode 100644 (file)
index 4938d95..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* 
- * linux/arch/sh/board/adx/setup.c
- *
- * Copyright (C) 2001 A&D Co., Ltd.
- *
- * I/O routine and setup routines for A&D ADX Board
- *
- * 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 <asm/machvec.h>
-#include <linux/module.h>
-
-extern void init_adx_IRQ(void);
-extern void *cf_io_base;
-
-const char *get_system_type(void)
-{
-       return "A&D ADX";
-}
-
-unsigned long adx_isa_port2addr(unsigned long offset)
-{
-       /* CompactFlash (IDE) */
-       if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset == 0x3f6)) {
-               return (unsigned long)cf_io_base + offset;
-       }
-
-       /* eth0 */
-       if ((offset >= 0x300) && (offset <= 0x30f)) {
-               return 0xa5000000 + offset;     /* COMM BOARD (AREA1) */
-       }
-
-       return offset + 0xb0000000; /* IOBUS (AREA 4)*/
-}
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_adx __initmv = {
-       .mv_nr_irqs             = 48,
-       .mv_isa_port2addr       = adx_isa_port2addr,
-       .mv_init_irq            = init_adx_IRQ,
-};
-ALIAS_MV(adx)
-
-int __init platform_setup(void)
-{
-       /* Nothing to see here .. */
-       return 0;
-}
-
index ac946a2201c7077d2e7af1f4e9c9d47da25dc59a..1ab04da36382c7ad96df8698231fd9bb4ff38e2f 100644 (file)
@@ -19,6 +19,7 @@
  * IRQ functions for a Hitachi Big Sur Evaluation Board.
  *
  */
+#undef DEBUG
 
 #include <linux/sched.h>
 #include <linux/module.h>
 #undef BIGSUR_DEBUG
 
 #ifdef BIGSUR_DEBUG
-#define DPRINTK(args...)        printk(args)
 #define DIPRINTK(n, args...)    if (BIGSUR_DEBUG>(n)) printk(args)
 #else
-#define DPRINTK(args...)
 #define DIPRINTK(n, args...)
 #endif /* BIGSUR_DEBUG */
 
@@ -60,45 +59,39 @@ extern int hd64465_irq_demux(int irq);
 /* Level 1 IRQ routines */
 static void disable_bigsur_l1irq(unsigned int irq)
 {
-        unsigned long flags;
         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) {
-                DPRINTK("Disable L1 IRQ %d\n", irq);
+                pr_debug("Disable L1 IRQ %d\n", irq);
                 DIPRINTK(2,"disable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
                         mask_port, bit);
-                local_irq_save(flags);
 
                 /* Disable IRQ - set mask bit */
                 mask = inb(mask_port) | bit;
                 outb(mask, mask_port);
-                local_irq_restore(flags);
                 return;
         }
-        DPRINTK("disable_bigsur_l1irq: Invalid IRQ %d\n", irq);
+        pr_debug("disable_bigsur_l1irq: Invalid IRQ %d\n", irq);
 }
 
 static void enable_bigsur_l1irq(unsigned int irq)
 {
-        unsigned long flags;
         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) {
-                DPRINTK("Enable L1 IRQ %d\n", irq);
+                pr_debug("Enable L1 IRQ %d\n", irq);
                 DIPRINTK(2,"enable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n",
                         mask_port, bit);
-                local_irq_save(flags);
                 /* Enable L1 IRQ - clear mask bit */
                 mask = inb(mask_port) & ~bit;
                 outb(mask, mask_port);
-                local_irq_restore(flags);
                 return;
         }
-        DPRINTK("enable_bigsur_l1irq: Invalid IRQ %d\n", irq);
+        pr_debug("enable_bigsur_l1irq: Invalid IRQ %d\n", irq);
 }
 
 
@@ -126,51 +119,45 @@ static const u32 imr_offset = BIGSUR_IMR0 - BIGSUR_IMR1;
 /* Level 2 IRQ routines */
 static void disable_bigsur_l2irq(unsigned int irq)
 {
-        unsigned long flags;
         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) {
-                DPRINTK("Disable L2 IRQ %d\n", irq);
+       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);
-                local_irq_save(flags);
 
                 /* Disable L2 IRQ - set mask bit */
                 mask = inb(mask_port) | bit;
                 outb(mask, mask_port);
-                local_irq_restore(flags);
                 return;
         }
-        DPRINTK("disable_bigsur_l2irq: Invalid IRQ %d\n", irq);
+        pr_debug("disable_bigsur_l2irq: Invalid IRQ %d\n", irq);
 }
 
 static void enable_bigsur_l2irq(unsigned int irq)
 {
-        unsigned long flags;
         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) {
-                DPRINTK("Enable L2 IRQ %d\n", irq);
+       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);
-                local_irq_save(flags);
 
                 /* Enable L2 IRQ - clear mask bit */
                 mask = inb(mask_port) & ~bit;
                 outb(mask, mask_port);
-                local_irq_restore(flags);
                 return;
         }
-        DPRINTK("enable_bigsur_l2irq: Invalid IRQ %d\n", irq);
+        pr_debug("enable_bigsur_l2irq: Invalid IRQ %d\n", irq);
 }
 
 static void mask_and_ack_bigsur(unsigned int irq)
 {
-        DPRINTK("mask_and_ack_bigsur IRQ %d\n", 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
@@ -179,7 +166,7 @@ static void mask_and_ack_bigsur(unsigned int irq)
 
 static void end_bigsur_irq(unsigned int irq)
 {
-        DPRINTK("end_bigsur_irq IRQ %d\n", 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);
@@ -193,7 +180,7 @@ static unsigned int startup_bigsur_irq(unsigned int irq)
         u8 mask;
         u32 reg;
 
-        DPRINTK("startup_bigsur_irq IRQ %d\n", irq);
+        pr_debug("startup_bigsur_irq IRQ %d\n", irq);
 
         if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
                 /* Enable the L1 IRQ */
@@ -218,7 +205,7 @@ static unsigned int startup_bigsur_irq(unsigned int irq)
 
 static void shutdown_bigsur_irq(unsigned int irq)
 {
-        DPRINTK("shutdown_bigsur_irq IRQ %d\n", irq);
+        pr_debug("shutdown_bigsur_irq IRQ %d\n", irq);
         if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)
                 disable_bigsur_l1irq(irq);
         else
@@ -260,7 +247,7 @@ static void make_bigsur_l1isr(unsigned int irq) {
                 disable_bigsur_l1irq(irq);
                 return;
         }
-        DPRINTK("make_bigsur_l1isr: bad irq, %d\n", irq);
+        pr_debug("make_bigsur_l1isr: bad irq, %d\n", irq);
         return;
 }
 
@@ -277,7 +264,7 @@ static void make_bigsur_l2isr(unsigned int irq) {
                 disable_bigsur_l2irq(irq);
                 return;
         }
-        DPRINTK("make_bigsur_l2isr: bad irq, %d\n", irq);
+        pr_debug("make_bigsur_l2isr: bad irq, %d\n", irq);
         return;
 }
 
index dfeede9da50f5129d570b61ee7a1d46d04448160..9711c20fc9e4b758a0e8e4b6f68ec024478f0b67 100644 (file)
 //             Big Sur Init Routines   
 /*===========================================================*/
 
-const char *get_system_type(void)
-{
-       return "Big Sur";
-}
-
-/*
- * The Machine Vector
- */
-extern void heartbeat_bigsur(void);
-extern void init_bigsur_IRQ(void);
-
-struct sh_machine_vector mv_bigsur __initmv = {
-       .mv_nr_irqs             = NR_IRQS,     // Defined in <asm/irq.h>
-
-       .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)
-
-int __init platform_setup(void)
+static void __init bigsur_setup(char **cmdline_p)
 {
        /* Mask all 2nd level IRQ's */
        outb(-1,BIGSUR_IMR0);
@@ -89,7 +65,24 @@ int __init platform_setup(void)
        outw(1, BIGSUR_ETHR+0xe);
        /* set the IO port to BIGSUR_ETHER_IOPORT */
        outw(BIGSUR_ETHER_IOPORT<<3, BIGSUR_ETHR+0x2);
-
-       return 0;
 }
 
+/*
+ * 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/cat68701/Makefile b/arch/sh/boards/cat68701/Makefile
deleted file mode 100644 (file)
index 52c1de0..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the CAT-68701 specific parts of the kernel
-#
-
-obj-y   := setup.o irq.o
-
diff --git a/arch/sh/boards/cat68701/irq.c b/arch/sh/boards/cat68701/irq.c
deleted file mode 100644 (file)
index f9a6d18..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * linux/arch/sh/boards/cat68701/irq.c
- *
- * Copyright (C) 2000  Niibe Yutaka
- *               2001  Yutaro Ebihara
- *
- * Setup routines for A-ONE Corp CAT-68701 SH7708 Board
- *
- * 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 <asm/irq.h>
-
-int cat68701_irq_demux(int irq)
-{
-        if(irq==13) return 14;
-        if(irq==7)  return 10;
-        return irq;
-}
-
-void init_cat68701_IRQ()
-{
-        make_imask_irq(10);
-        make_imask_irq(14);
-}
diff --git a/arch/sh/boards/cat68701/setup.c b/arch/sh/boards/cat68701/setup.c
deleted file mode 100644 (file)
index 90e5175..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* 
- * linux/arch/sh/boards/cat68701/setup.c
- *
- * Copyright (C) 2000  Niibe Yutaka
- *               2001  Yutaro Ebihara
- *
- * Setup routines for A-ONE Corp CAT-68701 SH7708 Board
- *
- * 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 <asm/io.h>
-#include <asm/machvec.h>
-#include <asm/mach/io.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-
-const char *get_system_type(void)
-{
-       return "CAT-68701";
-}
-
-#ifdef CONFIG_HEARTBEAT
-void heartbeat_cat68701()
-{
-        static unsigned int cnt = 0, period = 0 , bit = 0;
-        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(bit){ bit=0; }else{ bit=1; }
-       outw(bit<<15,0x3fe);
-}
-#endif /* CONFIG_HEARTBEAT */
-
-unsigned long cat68701_isa_port2addr(unsigned long offset)
-{
-       /* CompactFlash (IDE) */
-       if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset==0x3f6))
-               return 0xba000000 + offset;
-
-       /* INPUT PORT */
-       if ((offset >= 0x3fc) && (offset <= 0x3fd))
-               return 0xb4007000 + offset;
-
-       /* OUTPUT PORT */
-       if ((offset >= 0x3fe) && (offset <= 0x3ff))
-               return 0xb4007400 + offset;
-
-       return offset + 0xb4000000; /* other I/O (EREA 5)*/
-}
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_cat68701 __initmv = {
-       .mv_nr_irqs             = 32,
-       .mv_isa_port2addr       = cat68701_isa_port2addr,
-       .mv_irq_demux           = cat68701_irq_demux,
-
-       .mv_init_irq            = init_cat68701_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_cat68701,
-#endif
-};
-ALIAS_MV(cat68701)
-
-int __init platform_setup(void)
-{
-       /* dummy read erea5 (CS8900A) */
-}
-
diff --git a/arch/sh/boards/cqreek/Makefile b/arch/sh/boards/cqreek/Makefile
deleted file mode 100644 (file)
index 1a788a8..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the CqREEK specific parts of the kernel
-#
-
-obj-y   := setup.o irq.o
-
diff --git a/arch/sh/boards/cqreek/irq.c b/arch/sh/boards/cqreek/irq.c
deleted file mode 100644 (file)
index 2955adc..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/* $Id: irq.c,v 1.1.2.4 2002/11/04 20:33:56 lethal Exp $
- *
- * arch/sh/boards/cqreek/irq.c
- *
- * Copyright (C) 2000  Niibe Yutaka
- *
- * CqREEK IDE/ISA Bridge Support.
- *
- */
-
-#include <linux/irq.h>
-#include <linux/init.h>
-
-#include <asm/cqreek/cqreek.h>
-#include <asm/io.h>
-#include <asm/io_generic.h>
-#include <asm/irq.h>
-#include <asm/machvec.h>
-#include <asm/machvec_init.h>
-#include <asm/rtc.h>
-
-struct cqreek_irq_data {
-       unsigned short mask_port;       /* Port of Interrupt Mask Register */
-       unsigned short stat_port;       /* Port of Interrupt Status Register */
-       unsigned short bit;             /* Value of the bit */
-};
-static struct cqreek_irq_data cqreek_irq_data[NR_IRQS];
-
-static void disable_cqreek_irq(unsigned int irq)
-{
-       unsigned long flags;
-       unsigned short mask;
-       unsigned short mask_port = cqreek_irq_data[irq].mask_port;
-       unsigned short bit = cqreek_irq_data[irq].bit;
-
-       local_irq_save(flags);
-       /* Disable IRQ */
-       mask = inw(mask_port) & ~bit;
-       outw_p(mask, mask_port);
-       local_irq_restore(flags);
-}
-
-static void enable_cqreek_irq(unsigned int irq)
-{
-       unsigned long flags;
-       unsigned short mask;
-       unsigned short mask_port = cqreek_irq_data[irq].mask_port;
-       unsigned short bit = cqreek_irq_data[irq].bit;
-
-       local_irq_save(flags);
-       /* Enable IRQ */
-       mask = inw(mask_port) | bit;
-       outw_p(mask, mask_port);
-       local_irq_restore(flags);
-}
-
-static void mask_and_ack_cqreek(unsigned int irq)
-{
-       unsigned short stat_port = cqreek_irq_data[irq].stat_port;
-       unsigned short bit = cqreek_irq_data[irq].bit;
-
-       disable_cqreek_irq(irq);
-       /* Clear IRQ (it might be edge IRQ) */
-       inw(stat_port);
-       outw_p(bit, stat_port);
-}
-
-static void end_cqreek_irq(unsigned int irq)
-{
-       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-               enable_cqreek_irq(irq);
-}
-
-static unsigned int startup_cqreek_irq(unsigned int irq)
-{ 
-       enable_cqreek_irq(irq);
-       return 0;
-}
-
-static void shutdown_cqreek_irq(unsigned int irq)
-{
-       disable_cqreek_irq(irq);
-}
-
-static struct hw_interrupt_type cqreek_irq_type = {
-       .typename = "CqREEK-IRQ",
-       .startup = startup_cqreek_irq,
-       .shutdown = shutdown_cqreek_irq,
-       .enable = enable_cqreek_irq,
-       .disable = disable_cqreek_irq,
-       .ack = mask_and_ack_cqreek,
-       .end = end_cqreek_irq
-};
-
-int cqreek_has_ide, cqreek_has_isa;
-
-/* XXX: This is just for test for my NE2000 ISA board
-   What we really need is virtualized IRQ and demultiplexer like HP600 port */
-void __init init_cqreek_IRQ(void)
-{
-       if (cqreek_has_ide) {
-               cqreek_irq_data[14].mask_port = BRIDGE_IDE_INTR_MASK;
-               cqreek_irq_data[14].stat_port = BRIDGE_IDE_INTR_STAT;
-               cqreek_irq_data[14].bit = 1;
-
-               irq_desc[14].chip = &cqreek_irq_type;
-               irq_desc[14].status = IRQ_DISABLED;
-               irq_desc[14].action = 0;
-               irq_desc[14].depth = 1;
-
-               disable_cqreek_irq(14);
-       }
-
-       if (cqreek_has_isa) {
-               cqreek_irq_data[10].mask_port = BRIDGE_ISA_INTR_MASK;
-               cqreek_irq_data[10].stat_port = BRIDGE_ISA_INTR_STAT;
-               cqreek_irq_data[10].bit = (1 << 10);
-
-               /* XXX: Err... we may need demultiplexer for ISA irq... */
-               irq_desc[10].chip = &cqreek_irq_type;
-               irq_desc[10].status = IRQ_DISABLED;
-               irq_desc[10].action = 0;
-               irq_desc[10].depth = 1;
-
-               disable_cqreek_irq(10);
-       }
-}
-
diff --git a/arch/sh/boards/cqreek/setup.c b/arch/sh/boards/cqreek/setup.c
deleted file mode 100644 (file)
index eff4ed9..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/* $Id: setup.c,v 1.5 2003/08/04 01:51:58 lethal Exp $
- *
- * arch/sh/kernel/setup_cqreek.c
- *
- * Copyright (C) 2000  Niibe Yutaka
- *
- * CqREEK IDE/ISA Bridge Support.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/mach/cqreek.h>
-#include <asm/machvec.h>
-#include <asm/io.h>
-#include <asm/io_generic.h>
-#include <asm/irq.h>
-#include <asm/rtc.h>
-
-#define IDE_OFFSET 0xA4000000UL
-#define ISA_OFFSET 0xA4A00000UL
-
-const char *get_system_type(void)
-{
-       return "CqREEK";
-}
-
-static unsigned long cqreek_port2addr(unsigned long port)
-{
-       if (0x0000<=port && port<=0x0040)
-               return IDE_OFFSET + port;
-       if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6)
-               return IDE_OFFSET + port;
-
-       return ISA_OFFSET + port;
-}
-
-/*
- * The Machine Vector
- */
-struct sh_machine_vector mv_cqreek __initmv = {
-#if defined(CONFIG_CPU_SH4)
-       .mv_nr_irqs             = 48,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
-       .mv_nr_irqs             = 32,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
-       .mv_nr_irqs             = 61,
-#endif
-
-       .mv_init_irq            = init_cqreek_IRQ,
-
-       .mv_isa_port2addr       = cqreek_port2addr,
-};
-ALIAS_MV(cqreek)
-
-/*
- * Initialize the board
- */
-void __init platform_setup(void)
-{
-       int i;
-/* udelay is not available at setup time yet... */
-#define DELAY() do {for (i=0; i<10000; i++) ctrl_inw(0xa0000000);} while(0)
-
-       if ((inw (BRIDGE_FEATURE) & 1)) { /* We have IDE interface */
-               outw_p(0, BRIDGE_IDE_INTR_LVL);
-               outw_p(0, BRIDGE_IDE_INTR_MASK);
-
-               outw_p(0, BRIDGE_IDE_CTRL);
-               DELAY();
-
-               outw_p(0x8000, BRIDGE_IDE_CTRL);
-               DELAY();
-
-               outw_p(0xffff, BRIDGE_IDE_INTR_STAT); /* Clear interrupt status */
-               outw_p(0x0f-14, BRIDGE_IDE_INTR_LVL); /* Use 14 IPR */
-               outw_p(1, BRIDGE_IDE_INTR_MASK); /* Enable interrupt */
-               cqreek_has_ide=1;
-       }
-
-       if ((inw (BRIDGE_FEATURE) & 2)) { /* We have ISA interface */
-               outw_p(0, BRIDGE_ISA_INTR_LVL);
-               outw_p(0, BRIDGE_ISA_INTR_MASK);
-
-               outw_p(0, BRIDGE_ISA_CTRL);
-               DELAY();
-               outw_p(0x8000, BRIDGE_ISA_CTRL);
-               DELAY();
-
-               outw_p(0xffff, BRIDGE_ISA_INTR_STAT); /* Clear interrupt status */
-               outw_p(0x0f-10, BRIDGE_ISA_INTR_LVL); /* Use 10 IPR */
-               outw_p(0xfff8, BRIDGE_ISA_INTR_MASK); /* Enable interrupt */
-               cqreek_has_isa=1;
-       }
-
-       printk(KERN_INFO "CqREEK Setup (IDE=%d, ISA=%d)...done\n", cqreek_has_ide, cqreek_has_isa);
-}
-
diff --git a/arch/sh/boards/dmida/Makefile b/arch/sh/boards/dmida/Makefile
deleted file mode 100644 (file)
index 75999aa..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#
-# Makefile for the DataMyte Industrial Digital Assistant(tm) specific parts
-# of the kernel
-#
-
-obj-y   := mach.o
-
diff --git a/arch/sh/boards/dmida/mach.c b/arch/sh/boards/dmida/mach.c
deleted file mode 100644 (file)
index d03a25f..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * linux/arch/sh/boards/dmida/mach.c
- *
- * by Greg Banks <gbanks@pocketpenguins.com>
- * (c) 2000 PocketPenguins Inc
- *
- * Derived from mach_hp600.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.
- *
- * Machine vector for the DataMyte Industrial Digital Assistant(tm).
- * See http://www.dmida.com
- *
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/io.h>
-#include <asm/hd64465/hd64465.h>
-#include <asm/irq.h>
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_dmida __initmv = {
-       .mv_nr_irqs             = HD64465_IRQ_BASE+HD64465_IRQ_NUM,
-
-       .mv_inb                 = hd64465_inb,
-       .mv_inw                 = hd64465_inw,
-       .mv_inl                 = hd64465_inl,
-       .mv_outb                = hd64465_outb,
-       .mv_outw                = hd64465_outw,
-       .mv_outl                = hd64465_outl,
-
-       .mv_inb_p               = hd64465_inb_p,
-       .mv_inw_p               = hd64465_inw,
-       .mv_inl_p               = hd64465_inl,
-       .mv_outb_p              = hd64465_outb_p,
-       .mv_outw_p              = hd64465_outw,
-       .mv_outl_p              = hd64465_outl,
-
-       .mv_insb                = hd64465_insb,
-       .mv_insw                = hd64465_insw,
-       .mv_insl                = hd64465_insl,
-       .mv_outsb               = hd64465_outsb,
-       .mv_outsw               = hd64465_outsw,
-       .mv_outsl               = hd64465_outsl,
-
-       .mv_irq_demux           = hd64465_irq_demux,
-};
-ALIAS_MV(dmida)
-
index b10a6b11c0343e8c4390d5b550790e8cf2390dfb..5bf01f86c20c52cc4eb53969141838b9dc65884a 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/irq.h>
-
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/dreamcast/sysasic.h>
    event.
 
    There are three 32-bit ESRs located at 0xa05f8900 - 0xa05f6908.  Event
-   types can be found in include/asm-sh/dc_sysasic.h.  There are three groups
-   of EMRs that parallel the ESRs.  Each EMR group corresponds to an IRQ, so
-   0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928 triggers
-   IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9.
+   types can be found in include/asm-sh/dreamcast/sysasic.h. There are three
+   groups of EMRs that parallel the ESRs.  Each EMR group corresponds to an
+   IRQ, so 0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928
+   triggers IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9.
 
    In the kernel, these events are mapped to virtual IRQs so that drivers can
    respond to them as they would a normal interrupt.  In order to keep this
 /* Disable the hardware event by masking its bit in its EMR */
 static inline void disable_systemasic_irq(unsigned int irq)
 {
-        unsigned long flags;
         __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
         __u32 mask;
 
-        local_irq_save(flags);
         mask = inl(emr);
         mask &= ~(1 << EVENT_BIT(irq));
         outl(mask, emr);
-        local_irq_restore(flags);
 }
 
 /* Enable the hardware event by setting its bit in its EMR */
 static inline void enable_systemasic_irq(unsigned int irq)
 {
-        unsigned long flags;
         __u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
         __u32 mask;
 
-        local_irq_save(flags);
         mask = inl(emr);
         mask |= (1 << EVENT_BIT(irq));
         outl(mask, emr);
-        local_irq_restore(flags);
 }
 
 /* Acknowledge a hardware event by writing its bit back to its ESR */
index 379de1629134daa5b91c645a3ba228e0d55192d3..b3a876a3b85978363e7b9de6ccf5a464a026b55c 100644 (file)
@@ -1,4 +1,5 @@
-/* arch/sh/kernel/rtc-aica.c
+/*
+ * arch/sh/boards/dreamcast/rtc.c
  *
  * Dreamcast AICA RTC routines.
  *
  */
 
 #include <linux/time.h>
-
+#include <asm/rtc.h>
 #include <asm/io.h>
 
-extern void (*rtc_get_time)(struct timespec *);
-extern int (*rtc_set_time)(const time_t);
-
 /* The AICA RTC has an Epoch of 1/1/1950, so we must subtract 20 years (in
-   seconds to get the standard Unix Epoch when getting the time, and add 20
-   years when setting the time. */
+   seconds) to get the standard Unix Epoch when getting the time, and add
+   20 years when setting the time. */
 #define TWENTY_YEARS ((20 * 365LU + 5) * 86400)
 
 /* The AICA RTC is represented by a 32-bit seconds counter stored in 2 16-bit
@@ -32,7 +30,8 @@ extern int (*rtc_set_time)(const time_t);
  *
  * Grabs the current RTC seconds counter and adjusts it to the Unix Epoch.
  */
-void aica_rtc_gettimeofday(struct timespec *ts) {
+void aica_rtc_gettimeofday(struct timespec *ts)
+{
        unsigned long val1, val2;
 
        do {
@@ -55,7 +54,8 @@ void aica_rtc_gettimeofday(struct timespec *ts) {
  *
  * Adjusts the given @tv to the AICA Epoch and sets the RTC seconds counter.
  */
-int aica_rtc_settimeofday(const time_t secs) {
+int aica_rtc_settimeofday(const time_t secs)
+{
        unsigned long val1, val2;
        unsigned long adj = secs + TWENTY_YEARS;
 
@@ -75,7 +75,7 @@ int aica_rtc_settimeofday(const time_t secs) {
 
 void aica_time_init(void)
 {
-       rtc_get_time = aica_rtc_gettimeofday;
-       rtc_set_time = aica_rtc_settimeofday;
+       rtc_sh_get_time = aica_rtc_gettimeofday;
+       rtc_sh_set_time = aica_rtc_settimeofday;
 }
 
index 0027b80a23435cfd005e45f255ddd62fd5801a52..f13017eeeb27ebba6cb68571044155fcf7d6a5a0 100644 (file)
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/device.h>
-
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/rtc.h>
 #include <asm/machvec.h>
-#include <asm/machvec_init.h>
 #include <asm/mach/sysasic.h>
 
 extern struct hw_interrupt_type systemasic_int;
-/* XXX: Move this into it's proper header. */
-extern void (*board_time_init)(void);
 extern void aica_time_init(void);
 extern int gapspci_init(void);
 extern int systemasic_irq_demux(int);
 
-void *dreamcast_consistent_alloc(struct device *, size_t, dma_addr_t *, int);
+void *dreamcast_consistent_alloc(struct device *, size_t, dma_addr_t *, gfp_t);
 int dreamcast_consistent_free(struct device *, size_t, void *, dma_addr_t);
 
-const char *get_system_type(void)
-{
-       return "Sega Dreamcast";
-}
-
-struct sh_machine_vector mv_dreamcast __initmv = {
-       .mv_nr_irqs             = NR_IRQS,
-
-       .mv_irq_demux           = systemasic_irq_demux,
-
-#ifdef CONFIG_PCI
-       .mv_consistent_alloc    = dreamcast_consistent_alloc,
-       .mv_consistent_free     = dreamcast_consistent_free,
-#endif
-};
-ALIAS_MV(dreamcast)
-
-int __init platform_setup(void)
+static void __init dreamcast_setup(char **cmdline_p)
 {
        int i;
 
@@ -78,6 +58,16 @@ int __init platform_setup(void)
        if (gapspci_init() < 0)
                printk(KERN_WARNING "GAPSPCI was not detected.\n");
 #endif
-
-       return 0;
 }
+
+struct sh_machine_vector mv_dreamcast __initmv = {
+       .mv_name                = "Sega Dreamcast",
+       .mv_setup               = dreamcast_setup,
+       .mv_irq_demux           = systemasic_irq_demux,
+
+#ifdef CONFIG_PCI
+       .mv_consistent_alloc    = dreamcast_consistent_alloc,
+       .mv_consistent_free     = dreamcast_consistent_free,
+#endif
+};
+ALIAS_MV(dreamcast)
index 4b3ef16a0e960dc11d207966454e902dfc3e42c2..902bc975a13e0b82a03cae13bc1dbd06bceca698 100644 (file)
 #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>
 
-const char *get_system_type(void)
+static void __init ec3104_setup(char **cmdline_p)
 {
-       return "EC3104";
+       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,
@@ -48,31 +62,4 @@ struct sh_machine_vector mv_ec3104 __initmv = {
 
        .mv_irq_demux   = ec3104_irq_demux,
 };
-
 ALIAS_MV(ec3104)
-
-int __init platform_setup(void)
-{
-       char str[8];
-       int i;
-       
-       if (0)
-               return 0;
-
-       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].chip = &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);
-       
-       return 0;
-}
-
diff --git a/arch/sh/boards/harp/Makefile b/arch/sh/boards/harp/Makefile
deleted file mode 100644 (file)
index eb753d3..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for STMicroelectronics board specific parts of the kernel
-#
-
-obj-y := irq.o setup.o mach.o led.o
-
-obj-$(CONFIG_PCI) += pcidma.o
-
diff --git a/arch/sh/boards/harp/irq.c b/arch/sh/boards/harp/irq.c
deleted file mode 100644 (file)
index 96bb41c..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * Looks after interrupts on the HARP board.
- *
- * Bases on the IPR irq system
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/harp/harp.h>
-
-
-#define NUM_EXTERNAL_IRQS 16
-
-// Early versions of the STB1 Overdrive required this nasty frig
-//#define INVERT_INTMASK_WRITES
-
-static void enable_harp_irq(unsigned int irq);
-static void disable_harp_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_harp_irq disable_harp_irq
-
-static void mask_and_ack_harp(unsigned int);
-static void end_harp_irq(unsigned int irq);
-
-static unsigned int startup_harp_irq(unsigned int irq)
-{
-       enable_harp_irq(irq);
-       return 0;               /* never anything pending */
-}
-
-static struct hw_interrupt_type harp_irq_type = {
-       .typename = "Harp-IRQ",
-       .startup = startup_harp_irq,
-       .shutdown = shutdown_harp_irq,
-       .enable = enable_harp_irq,
-       .disable = disable_harp_irq,
-       .ack = mask_and_ack_harp,
-       .end = end_harp_irq
-};
-
-static void disable_harp_irq(unsigned int irq)
-{
-       unsigned val, flags;
-       unsigned maskReg;
-       unsigned mask;
-       int pri;
-
-       if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
-               return;
-
-       pri = 15 - irq;
-
-       if (pri < 8) {
-               maskReg = EPLD_INTMASK0;
-       } else {
-               maskReg = EPLD_INTMASK1;
-               pri -= 8;
-       }
-
-       local_irq_save(flags);
-       mask = ctrl_inl(maskReg);
-       mask &= (~(1 << pri));
-#if defined(INVERT_INTMASK_WRITES)
-       mask ^= 0xff;
-#endif
-       ctrl_outl(mask, maskReg);
-       local_irq_restore(flags);
-}
-
-static void enable_harp_irq(unsigned int irq)
-{
-       unsigned flags;
-       unsigned maskReg;
-       unsigned mask;
-       int pri;
-
-       if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
-               return;
-
-       pri = 15 - irq;
-
-       if (pri < 8) {
-               maskReg = EPLD_INTMASK0;
-       } else {
-               maskReg = EPLD_INTMASK1;
-               pri -= 8;
-       }
-
-       local_irq_save(flags);
-       mask = ctrl_inl(maskReg);
-
-
-       mask |= (1 << pri);
-
-#if defined(INVERT_INTMASK_WRITES)
-       mask ^= 0xff;
-#endif
-       ctrl_outl(mask, maskReg);
-
-       local_irq_restore(flags);
-}
-
-/* This functions sets the desired irq handler to be an overdrive type */
-static void __init make_harp_irq(unsigned int irq)
-{
-       disable_irq_nosync(irq);
-       irq_desc[irq].chip = &harp_irq_type;
-       disable_harp_irq(irq);
-}
-
-static void mask_and_ack_harp(unsigned int irq)
-{
-       disable_harp_irq(irq);
-}
-
-static void end_harp_irq(unsigned int irq)
-{
-       enable_harp_irq(irq);
-}
-
-void __init init_harp_irq(void)
-{
-       int i;
-
-#if !defined(INVERT_INTMASK_WRITES)
-       // On the harp these are set to enable an interrupt
-       ctrl_outl(0x00, EPLD_INTMASK0);
-       ctrl_outl(0x00, EPLD_INTMASK1);
-#else
-       // On the Overdrive the data is inverted before being stored in the reg
-       ctrl_outl(0xff, EPLD_INTMASK0);
-       ctrl_outl(0xff, EPLD_INTMASK1);
-#endif
-
-       for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
-               make_harp_irq(i);
-       }
-}
diff --git a/arch/sh/boards/harp/led.c b/arch/sh/boards/harp/led.c
deleted file mode 100644 (file)
index aeb7b39..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * linux/arch/sh/stboards/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 ST40STB1 HARP and compatible code.
- */
-
-#include <asm/io.h>
-#include <asm/harp/harp.h>
-
-/* Harp: Flash LD10 (front pannel) connected to EPLD (IC8) */
-/* Overdrive: Flash LD1 (front panel) connected to EPLD (IC4) */
-/* Works for HARP and overdrive */
-static void mach_led(int position, int value)
-{
-       if (value) {
-               ctrl_outl(EPLD_LED_ON, EPLD_LED);
-       } else {
-               ctrl_outl(EPLD_LED_OFF, EPLD_LED);
-       }
-}
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* acts like an actual heart beat -- ie thump-thump-pause... */
-void heartbeat_harp(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
diff --git a/arch/sh/boards/harp/mach.c b/arch/sh/boards/harp/mach.c
deleted file mode 100644 (file)
index a946dd1..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * linux/arch/sh/boards/harp/mach.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.
- *
- * Machine vector for the STMicroelectronics STB1 HARP and compatible boards
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-#include <asm/hd64465/io.h>
-#include <asm/hd64465/hd64465.h>
-
-void setup_harp(void);
-void init_harp_irq(void);
-void heartbeat_harp(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_harp __initmv = {
-       .mv_nr_irqs             = 89 + HD64465_IRQ_NUM,
-
-       .mv_inb                 = hd64465_inb,
-       .mv_inw                 = hd64465_inw,
-       .mv_inl                 = hd64465_inl,
-       .mv_outb                = hd64465_outb,
-       .mv_outw                = hd64465_outw,
-       .mv_outl                = hd64465_outl,
-
-       .mv_inb_p               = hd64465_inb_p,
-       .mv_inw_p               = hd64465_inw,
-       .mv_inl_p               = hd64465_inl,
-       .mv_outb_p              = hd64465_outb_p,
-       .mv_outw_p              = hd64465_outw,
-       .mv_outl_p              = hd64465_outl,
-
-       .mv_insb                = hd64465_insb,
-       .mv_insw                = hd64465_insw,
-       .mv_insl                = hd64465_insl,
-       .mv_outsb               = hd64465_outsb,
-       .mv_outsw               = hd64465_outsw,
-       .mv_outsl               = hd64465_outsl,
-
-        .mv_isa_port2addr       = hd64465_isa_port2addr,
-
-#ifdef CONFIG_PCI
-       .mv_init_irq            = init_harp_irq,
-#endif
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_harp,
-#endif
-};
-
-ALIAS_MV(harp)
diff --git a/arch/sh/boards/harp/pcidma.c b/arch/sh/boards/harp/pcidma.c
deleted file mode 100644 (file)
index 4753113..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 
- * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * Dynamic DMA mapping support.
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/addrspace.h>
-
-
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                          dma_addr_t * dma_handle)
-{
-       void *ret;
-       int gfp = GFP_ATOMIC;
-
-       ret = (void *) __get_free_pages(gfp, get_order(size));
-
-       if (ret != NULL) {
-               /* Is it neccessary to do the memset? */
-               memset(ret, 0, size);
-               *dma_handle = virt_to_bus(ret);
-       }
-       /* We must flush the cache before we pass it on to the device */
-       flush_cache_all();
-       return  P2SEGADDR(ret);
-}
-
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-                        void *vaddr, dma_addr_t dma_handle)
-{
-        unsigned long p1addr=P1SEGADDR((unsigned long)vaddr);
-
-       free_pages(p1addr, get_order(size));
-}
diff --git a/arch/sh/boards/harp/setup.c b/arch/sh/boards/harp/setup.c
deleted file mode 100644 (file)
index 886e450..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * arch/sh/stboard/setup.c
- *
- * Copyright (C) 2001 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.
- *
- * STMicroelectronics ST40STB1 HARP and compatible support.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <asm/harp/harp.h>
-
-const char *get_system_type(void)
-{
-       return "STB1 Harp";
-}
-
-/*
- * Initialize the board
- */
-int __init platform_setup(void)
-{
-#ifdef CONFIG_SH_STB1_HARP
-       unsigned long ic8_version, ic36_version;
-
-       ic8_version = ctrl_inl(EPLD_REVID2);
-       ic36_version = ctrl_inl(EPLD_REVID1);
-
-        printk("STMicroelectronics STB1 HARP initialisaton\n");
-        printk("EPLD versions: IC8: %d.%02d, IC36: %d.%02d\n",
-               (ic8_version >> 4) & 0xf, ic8_version & 0xf,
-               (ic36_version >> 4) & 0xf, ic36_version & 0xf);
-#elif defined(CONFIG_SH_STB1_OVERDRIVE)
-       unsigned long version;
-
-       version = ctrl_inl(EPLD_REVID);
-
-        printk("STMicroelectronics STB1 Overdrive initialisaton\n");
-        printk("EPLD version: %d.%02d\n",
-              (version >> 4) & 0xf, version & 0xf);
-#else
-#error Undefined machine
-#endif
-        /* Currently all STB1 chips have problems with the sleep instruction,
-         * so disable it here.
-         */
-       disable_hlt();
-
-       return 0;
-}
-
-/*
- * pcibios_map_platform_irq
- *
- * This is board specific and returns the IRQ for a given PCI device.
- * It is used by the PCI code (arch/sh/kernel/st40_pci*)
- *
- */
-
-#define HARP_PCI_IRQ    1
-#define HARP_BRIDGE_IRQ 2
-#define OVERDRIVE_SLOT0_IRQ 0
-
-
-int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       switch (slot) {
-#ifdef CONFIG_SH_STB1_HARP
-       case 2:         /*This is the PCI slot on the */
-               return HARP_PCI_IRQ;
-       case 1:         /* this is the bridge */
-               return HARP_BRIDGE_IRQ;
-#elif defined(CONFIG_SH_STB1_OVERDRIVE)
-       case 1:
-       case 2:
-       case 3:
-               return slot - 1;
-#else
-#error Unknown board
-#endif
-       default:
-               return -1;
-       }
-}
-
index 927fe0aa5dfa7ba65daddf881d9ca41577cedd4d..ff1b7f5b4e918a03378d78c50efb9772b7a85fcf 100644 (file)
@@ -2,5 +2,6 @@
 # Makefile for the HP6xx specific parts of the kernel
 #
 
-obj-y   := mach.o setup.o
-
+obj-y                  := setup.o
+obj-$(CONFIG_PM)       += pm.o pm_wakeup.o
+obj-$(CONFIG_APM)      += hp6xx_apm.o
diff --git a/arch/sh/boards/hp6xx/hp6xx_apm.c b/arch/sh/boards/hp6xx/hp6xx_apm.c
new file mode 100644 (file)
index 0000000..ad0e712
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * bios-less APM driver for hp680
+ *
+ * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/apm_bios.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/apm.h>
+#include <asm/adc.h>
+#include <asm/hp6xx/hp6xx.h>
+
+#define SH7709_PGDR                    0xa400012c
+
+#define APM_CRITICAL                   10
+#define APM_LOW                                30
+
+#define HP680_BATTERY_MAX              875
+#define HP680_BATTERY_MIN              600
+#define HP680_BATTERY_AC_ON            900
+
+#define MODNAME "hp6x0_apm"
+
+static int hp6x0_apm_get_info(char *buf, char **start, off_t fpos, int length)
+{
+       u8 pgdr;
+       char *p;
+       int battery_status;
+       int battery_flag;
+       int ac_line_status;
+       int time_units = APM_BATTERY_LIFE_UNKNOWN;
+
+       int battery = adc_single(ADC_CHANNEL_BATTERY);
+       int backup = adc_single(ADC_CHANNEL_BACKUP);
+       int charging = adc_single(ADC_CHANNEL_CHARGE);
+       int percentage;
+
+       percentage = 100 * (battery - HP680_BATTERY_MIN) /
+                          (HP680_BATTERY_MAX - HP680_BATTERY_MIN);
+
+       ac_line_status = (battery > HP680_BATTERY_AC_ON) ?
+                        APM_AC_ONLINE : APM_AC_OFFLINE;
+
+       p = buf;
+
+       pgdr = ctrl_inb(SH7709_PGDR);
+       if (pgdr & PGDR_MAIN_BATTERY_OUT) {
+               battery_status = APM_BATTERY_STATUS_NOT_PRESENT;
+               battery_flag = 0x80;
+               percentage = -1;
+       } else if (charging < 8 ) {
+               battery_status = APM_BATTERY_STATUS_CHARGING;
+               battery_flag = 0x08;
+               ac_line_status = 0xff;
+       } else if (percentage <= APM_CRITICAL) {
+               battery_status = APM_BATTERY_STATUS_CRITICAL;
+               battery_flag = 0x04;
+       } else if (percentage <= APM_LOW) {
+               battery_status = APM_BATTERY_STATUS_LOW;
+               battery_flag = 0x02;
+       } else {
+               battery_status = APM_BATTERY_STATUS_HIGH;
+               battery_flag = 0x01;
+       }
+
+       p += sprintf(p, "1.0 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n",
+                    APM_32_BIT_SUPPORT,
+                    ac_line_status,
+                    battery_status,
+                    battery_flag,
+                    percentage,
+                    time_units,
+                    "min");
+       p += sprintf(p, "bat=%d backup=%d charge=%d\n",
+                    battery, backup, charging);
+
+       return p - buf;
+}
+
+static irqreturn_t hp6x0_apm_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+       if (!apm_suspended)
+               apm_queue_event(APM_USER_SUSPEND);
+
+       return IRQ_HANDLED;
+}
+
+static int __init hp6x0_apm_init(void)
+{
+       int ret;
+
+       ret = request_irq(HP680_BTN_IRQ, hp6x0_apm_interrupt,
+                         SA_INTERRUPT, MODNAME, 0);
+       if (unlikely(ret < 0)) {
+               printk(KERN_ERR MODNAME ": IRQ %d request failed\n",
+                      HP680_BTN_IRQ);
+               return ret;
+       }
+
+       apm_get_info = hp6x0_apm_get_info;
+
+       return ret;
+}
+
+static void __exit hp6x0_apm_exit(void)
+{
+       free_irq(HP680_BTN_IRQ, 0);
+       apm_get_info = 0;
+}
+
+module_init(hp6x0_apm_init);
+module_exit(hp6x0_apm_exit);
+
+MODULE_AUTHOR("Adriy Skulysh");
+MODULE_DESCRIPTION("hp6xx Advanced Power Management");
+MODULE_LICENSE("GPL");
diff --git a/arch/sh/boards/hp6xx/pm.c b/arch/sh/boards/hp6xx/pm.c
new file mode 100644 (file)
index 0000000..0e501bc
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * hp6x0 Power Management Routines
+ *
+ * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <asm/io.h>
+#include <asm/hd64461.h>
+#include <asm/hp6xx/hp6xx.h>
+#include <asm/cpu/dac.h>
+#include <asm/pm.h>
+
+#define STBCR          0xffffff82
+#define STBCR2         0xffffff88
+
+static int hp6x0_pm_enter(suspend_state_t state)
+{
+       u8 stbcr, stbcr2;
+#ifdef CONFIG_HD64461_ENABLER
+       u8 scr;
+       u16 hd64461_stbcr;
+#endif
+
+       if (state != PM_SUSPEND_MEM)
+               return -EINVAL;
+
+#ifdef CONFIG_HD64461_ENABLER
+       outb(0, HD64461_PCC1CSCIER);
+
+       scr = inb(HD64461_PCC1SCR);
+       scr |= HD64461_PCCSCR_VCC1;
+       outb(scr, HD64461_PCC1SCR);
+
+       hd64461_stbcr = inw(HD64461_STBCR);
+       hd64461_stbcr |= HD64461_STBCR_SPC1ST;
+       outw(hd64461_stbcr, HD64461_STBCR);
+#endif
+
+       ctrl_outb(0x1f, DACR);
+
+       stbcr = ctrl_inb(STBCR);
+       ctrl_outb(0x01, STBCR);
+
+       stbcr2 = ctrl_inb(STBCR2);
+       ctrl_outb(0x7f , STBCR2);
+
+       outw(0xf07f, HD64461_SCPUCR);
+
+       pm_enter();
+
+       outw(0, HD64461_SCPUCR);
+       ctrl_outb(stbcr, STBCR);
+       ctrl_outb(stbcr2, STBCR2);
+
+#ifdef CONFIG_HD64461_ENABLER
+       hd64461_stbcr = inw(HD64461_STBCR);
+       hd64461_stbcr &= ~HD64461_STBCR_SPC1ST;
+       outw(hd64461_stbcr, HD64461_STBCR);
+
+       outb(0x4c, HD64461_PCC1CSCIER);
+       outb(0x00, HD64461_PCC1CSCR);
+#endif
+
+       return 0;
+}
+
+/*
+ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
+ */
+static struct pm_ops hp6x0_pm_ops = {
+       .pm_disk_mode   = PM_DISK_FIRMWARE,
+       .enter          = hp6x0_pm_enter,
+};
+
+static int __init hp6x0_pm_init(void)
+{
+       pm_set_ops(&hp6x0_pm_ops);
+       return 0;
+}
+
+late_initcall(hp6x0_pm_init);
diff --git a/arch/sh/boards/hp6xx/pm_wakeup.S b/arch/sh/boards/hp6xx/pm_wakeup.S
new file mode 100644 (file)
index 0000000..45e9bf0
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
+ *
+ * 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/linkage.h>
+#include <asm/cpu/mmu_context.h>
+
+#define k0     r0
+#define k1     r1
+#define k2     r2
+#define k3     r3
+#define k4     r4
+
+/*
+ * Kernel mode register usage:
+ *     k0      scratch
+ *     k1      scratch
+ *     k2      scratch (Exception code)
+ *     k3      scratch (Return address)
+ *     k4      scratch
+ *     k5      reserved
+ *     k6      Global Interrupt Mask (0--15 << 4)
+ *     k7      CURRENT_THREAD_INFO (pointer to current thread info)
+ */
+
+ENTRY(wakeup_start)
+! clear STBY bit
+       mov     #-126, k2
+       and     #127, k0
+       mov.b   k0, @k2
+! enable refresh
+       mov.l   5f, k1
+       mov.w   6f, k0
+       mov.w   k0, @k1
+! jump to handler
+       mov.l   2f, k2
+       mov.l   3f, k3
+       mov.l   @k2, k2
+
+       mov.l   4f, k1
+       jmp     @k1
+       nop
+
+       .align  2
+1:     .long   EXPEVT
+2:     .long   INTEVT
+3:     .long   ret_from_irq
+4:     .long   handle_exception
+5:     .long   0xffffff68
+6:     .word   0x0524
+
+ENTRY(wakeup_end)
+       nop
index 71f315663cc964fb3c51f4b40963ea015b522b8c..60ab17ad60544d79111f8ab807943875f1fa8780 100644 (file)
@@ -8,22 +8,22 @@
  *
  * Setup code for an HP680  (internal peripherials only)
  */
-
+#include <linux/types.h>
 #include <linux/init.h>
-#include <asm/io.h>
 #include <asm/hd64461.h>
+#include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/hp6xx/hp6xx.h>
 #include <asm/cpu/dac.h>
 
-const char *get_system_type(void)
-{
-       return "HP6xx";
-}
+#define        SCPCR   0xa4000116
+#define SCPDR  0xa4000136
 
-int __init platform_setup(void)
+static void __init hp6xx_setup(char **cmdline_p)
 {
        u8 v8;
        u16 v;
+
        v = inw(HD64461_STBCR);
        v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST |
            HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
@@ -50,5 +50,51 @@ int __init platform_setup(void)
        v8 &= ~DACR_DAE;
        ctrl_outb(v8,DACR);
 
-       return 0;
+       v8 = ctrl_inb(SCPDR);
+       v8 |= SCPDR_TS_SCAN_X | SCPDR_TS_SCAN_Y;
+       v8 &= ~SCPDR_TS_SCAN_ENABLE;
+       ctrl_outb(v8, SCPDR);
+
+       v = ctrl_inw(SCPCR);
+       v &= ~SCPCR_TS_MASK;
+       v |= SCPCR_TS_ENABLE;
+       ctrl_outw(v, SCPCR);
 }
+
+/*
+ * XXX: This is stupid, we should have a generic machine vector for the cchips
+ * and just wrap the platform setup code in to this, as it's the only thing
+ * that ends up being different.
+ */
+struct sh_machine_vector mv_hp6xx __initmv = {
+       .mv_name = "hp6xx",
+       .mv_setup = hp6xx_setup,
+       .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM,
+
+       .mv_inb = hd64461_inb,
+       .mv_inw = hd64461_inw,
+       .mv_inl = hd64461_inl,
+       .mv_outb = hd64461_outb,
+       .mv_outw = hd64461_outw,
+       .mv_outl = hd64461_outl,
+
+       .mv_inb_p = hd64461_inb_p,
+       .mv_inw_p = hd64461_inw,
+       .mv_inl_p = hd64461_inl,
+       .mv_outb_p = hd64461_outb_p,
+       .mv_outw_p = hd64461_outw,
+       .mv_outl_p = hd64461_outl,
+
+       .mv_insb = hd64461_insb,
+       .mv_insw = hd64461_insw,
+       .mv_insl = hd64461_insl,
+       .mv_outsb = hd64461_outsb,
+       .mv_outsw = hd64461_outsw,
+       .mv_outsl = hd64461_outsl,
+
+       .mv_readw = hd64461_readw,
+       .mv_writew = hd64461_writew,
+
+       .mv_irq_demux = hd64461_irq_demux,
+};
+ALIAS_MV(hp6xx)
diff --git a/arch/sh/boards/landisk/Makefile b/arch/sh/boards/landisk/Makefile
new file mode 100644 (file)
index 0000000..89e4beb
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for I-O DATA DEVICE, INC. "LANDISK Series"
+#
+
+obj-y   := setup.o io.o irq.o rtc.o landisk_pwb.o
diff --git a/arch/sh/boards/landisk/io.c b/arch/sh/boards/landisk/io.c
new file mode 100644 (file)
index 0000000..92498b4
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * arch/sh/boards/landisk/io.c
+ *
+ * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for I-O Data Device, Inc. LANDISK.
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_landisk.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+/*
+ * modifed by kogiidena
+ * 2005.03.03
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <asm/landisk/iodata_landisk.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+
+extern void *area5_io_base;    /* Area 5 I/O Base address */
+extern void *area6_io_base;    /* Area 6 I/O Base address */
+
+static inline unsigned long port2adr(unsigned int port)
+{
+       if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+               if (port == 0x3f6)
+                       return ((unsigned long)area5_io_base + 0x2c);
+               else
+                       return ((unsigned long)area5_io_base + PA_PIDE_OFFSET +
+                               ((port - 0x1f0) << 1));
+       else if ((0x170 <= port && port < 0x178) || port == 0x376)
+               if (port == 0x376)
+                       return ((unsigned long)area6_io_base + 0x2c);
+               else
+                       return ((unsigned long)area6_io_base + PA_SIDE_OFFSET +
+                               ((port - 0x170) << 1));
+       else
+               maybebadio((unsigned long)port);
+
+       return port;
+}
+
+/*
+ * 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.
+ */
+u8 landisk_inb(unsigned long port)
+{
+       if (PXSEG(port))
+               return ctrl_inb(port);
+       else if (is_pci_ioaddr(port))
+               return ctrl_inb(pci_ioaddr(port));
+
+       return ctrl_inw(port2adr(port)) & 0xff;
+}
+
+u8 landisk_inb_p(unsigned long port)
+{
+       u8 v;
+
+       if (PXSEG(port))
+               v = ctrl_inb(port);
+       else if (is_pci_ioaddr(port))
+               v = ctrl_inb(pci_ioaddr(port));
+       else
+               v = ctrl_inw(port2adr(port)) & 0xff;
+
+       ctrl_delay();
+
+       return v;
+}
+
+u16 landisk_inw(unsigned long port)
+{
+       if (PXSEG(port))
+               return ctrl_inw(port);
+       else if (is_pci_ioaddr(port))
+               return ctrl_inw(pci_ioaddr(port));
+       else
+               maybebadio(port);
+
+       return 0;
+}
+
+u32 landisk_inl(unsigned long port)
+{
+       if (PXSEG(port))
+               return ctrl_inl(port);
+       else if (is_pci_ioaddr(port))
+               return ctrl_inl(pci_ioaddr(port));
+       else
+               maybebadio(port);
+
+       return 0;
+}
+
+void landisk_outb(u8 value, unsigned long port)
+{
+       if (PXSEG(port))
+               ctrl_outb(value, port);
+       else if (is_pci_ioaddr(port))
+               ctrl_outb(value, pci_ioaddr(port));
+       else
+               ctrl_outw(value, port2adr(port));
+}
+
+void landisk_outb_p(u8 value, unsigned long port)
+{
+       if (PXSEG(port))
+               ctrl_outb(value, port);
+       else if (is_pci_ioaddr(port))
+               ctrl_outb(value, pci_ioaddr(port));
+       else
+               ctrl_outw(value, port2adr(port));
+       ctrl_delay();
+}
+
+void landisk_outw(u16 value, unsigned long port)
+{
+       if (PXSEG(port))
+               ctrl_outw(value, port);
+       else if (is_pci_ioaddr(port))
+               ctrl_outw(value, pci_ioaddr(port));
+       else
+               maybebadio(port);
+}
+
+void landisk_outl(u32 value, unsigned long port)
+{
+       if (PXSEG(port))
+               ctrl_outl(value, port);
+       else if (is_pci_ioaddr(port))
+               ctrl_outl(value, pci_ioaddr(port));
+       else
+               maybebadio(port);
+}
+
+void landisk_insb(unsigned long port, void *dst, unsigned long count)
+{
+        volatile u16 *p;
+        u8 *buf = dst;
+
+        if (PXSEG(port)) {
+                while (count--)
+                        *buf++ = *(volatile u8 *)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);
+                while (count--)
+                        *buf++ = *p & 0xff;
+       }
+}
+
+void landisk_insw(unsigned long port, void *dst, unsigned long count)
+{
+        volatile u16 *p;
+        u16 *buf = dst;
+
+       if (PXSEG(port))
+               p = (volatile u16 *)port;
+       else if (is_pci_ioaddr(port))
+               p = (volatile u16 *)pci_ioaddr(port);
+       else
+               p = (volatile u16 *)port2adr(port);
+       while (count--)
+               *buf++ = *p;
+}
+
+void landisk_insl(unsigned long port, void *dst, unsigned long count)
+{
+        u32 *buf = dst;
+
+       if (is_pci_ioaddr(port)) {
+                volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+                while (count--)
+                        *buf++ = *p;
+       } else
+               maybebadio(port);
+}
+
+void landisk_outsb(unsigned long port, const void *src, unsigned long count)
+{
+        volatile u16 *p;
+        const u8 *buf = src;
+
+       if (PXSEG(port))
+                while (count--)
+                        ctrl_outb(*buf++, 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);
+                while (count--)
+                        *p = *buf++;
+       }
+}
+
+void landisk_outsw(unsigned long port, const void *src, unsigned long count)
+{
+        volatile u16 *p;
+        const u16 *buf = src;
+
+       if (PXSEG(port))
+                p = (volatile u16 *)port;
+       else if (is_pci_ioaddr(port))
+                p = (volatile u16 *)pci_ioaddr(port);
+       else
+                p = (volatile u16 *)port2adr(port);
+
+        while (count--)
+                *p = *buf++;
+}
+
+void landisk_outsl(unsigned long port, const void *src, unsigned long count)
+{
+        const u32 *buf = src;
+
+       if (is_pci_ioaddr(port)) {
+                volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+                while (count--)
+                        *p = *buf++;
+       } else
+               maybebadio(port);
+}
+
+void __iomem *landisk_ioport_map(unsigned long port, unsigned int size)
+{
+        if (PXSEG(port))
+                return (void __iomem *)port;
+        else if (is_pci_ioaddr(port))
+                return (void __iomem *)pci_ioaddr(port);
+
+        return (void __iomem *)port2adr(port);
+}
diff --git a/arch/sh/boards/landisk/irq.c b/arch/sh/boards/landisk/irq.c
new file mode 100644 (file)
index 0000000..a006d64
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * arch/sh/boards/landisk/irq.c
+ *
+ * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for I-O Data Device, Inc. LANDISK.
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_landisk.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+/*
+ * modified by kogiidena
+ * 2005.03.03
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/landisk/iodata_landisk.h>
+
+static void enable_landisk_irq(unsigned int irq);
+static void disable_landisk_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_landisk_irq disable_landisk_irq
+
+static void ack_landisk_irq(unsigned int irq);
+static void end_landisk_irq(unsigned int irq);
+
+static unsigned int startup_landisk_irq(unsigned int irq)
+{
+       enable_landisk_irq(irq);
+       return 0;               /* never anything pending */
+}
+
+static void disable_landisk_irq(unsigned int irq)
+{
+       unsigned char val;
+       unsigned char mask = 0xff ^ (0x01 << (irq - 5));
+
+       /* Set the priority in IPR to 0 */
+       val = ctrl_inb(PA_IMASK);
+       val &= mask;
+       ctrl_outb(val, PA_IMASK);
+}
+
+static void enable_landisk_irq(unsigned int irq)
+{
+       unsigned char val;
+       unsigned char value = (0x01 << (irq - 5));
+
+       /* Set priority in IPR back to original value */
+       val = ctrl_inb(PA_IMASK);
+       val |= value;
+       ctrl_outb(val, PA_IMASK);
+}
+
+static void ack_landisk_irq(unsigned int irq)
+{
+       disable_landisk_irq(irq);
+}
+
+static void end_landisk_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+               enable_landisk_irq(irq);
+}
+
+static struct hw_interrupt_type landisk_irq_type = {
+       .typename = "LANDISK IRQ",
+       .startup = startup_landisk_irq,
+       .shutdown = shutdown_landisk_irq,
+       .enable = enable_landisk_irq,
+       .disable = disable_landisk_irq,
+       .ack = ack_landisk_irq,
+       .end = end_landisk_irq
+};
+
+static void make_landisk_irq(unsigned int irq)
+{
+       disable_irq_nosync(irq);
+       irq_desc[irq].handler = &landisk_irq_type;
+       disable_landisk_irq(irq);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_landisk_IRQ(void)
+{
+       int i;
+
+       for (i = 5; i < 14; i++)
+               make_landisk_irq(i);
+}
diff --git a/arch/sh/boards/landisk/landisk_pwb.c b/arch/sh/boards/landisk/landisk_pwb.c
new file mode 100644 (file)
index 0000000..e75cb57
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * arch/sh/boards/landisk/landisk_pwb.c -- driver for the Power control switch.
+ *
+ * This driver will also support the I-O DATA Device, Inc. LANDISK Board.
+ *
+ * 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.
+ *
+ * Copylight (C) 2002 Atom Create Engineering Co., Ltd.
+ *
+ * LED control drive function added by kogiidena
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/major.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/landisk/iodata_landisk.h>
+
+#define SHUTDOWN_BTN_MINOR     1       /* Shutdown button device minor no. */
+#define LED_MINOR             21       /* LED minor no. */
+#define BTN_MINOR             22       /* BUTTON minor no. */
+#define GIO_MINOR             40       /* GIO minor no. */
+
+static int openCnt;
+static int openCntLED;
+static int openCntGio;
+static int openCntBtn;
+static int landisk_btn;
+static int landisk_btnctrlpid;
+/*
+ * Functions prototypes
+ */
+
+static int gio_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+                    unsigned long arg);
+
+static int swdrv_open(struct inode *inode, struct file *filp)
+{
+       int minor;
+
+       minor = MINOR(inode->i_rdev);
+       filp->private_data = (void *)minor;
+
+       if (minor == SHUTDOWN_BTN_MINOR) {
+               if (openCnt > 0) {
+                       return -EALREADY;
+               } else {
+                       openCnt++;
+                       return 0;
+               }
+       } else if (minor == LED_MINOR) {
+               if (openCntLED > 0) {
+                       return -EALREADY;
+               } else {
+                       openCntLED++;
+                       return 0;
+               }
+       } else if (minor == BTN_MINOR) {
+               if (openCntBtn > 0) {
+                       return -EALREADY;
+               } else {
+                       openCntBtn++;
+                       return 0;
+               }
+       } else if (minor == GIO_MINOR) {
+               if (openCntGio > 0) {
+                       return -EALREADY;
+               } else {
+                       openCntGio++;
+                       return 0;
+               }
+       }
+       return -ENOENT;
+
+}
+
+static int swdrv_close(struct inode *inode, struct file *filp)
+{
+       int minor;
+
+       minor = MINOR(inode->i_rdev);
+       if (minor == SHUTDOWN_BTN_MINOR) {
+               openCnt--;
+       } else if (minor == LED_MINOR) {
+               openCntLED--;
+       } else if (minor == BTN_MINOR) {
+               openCntBtn--;
+       } else if (minor == GIO_MINOR) {
+               openCntGio--;
+       }
+       return 0;
+}
+
+static int swdrv_read(struct file *filp, char *buff, size_t count,
+                     loff_t * ppos)
+{
+       int minor;
+       minor = (int)(filp->private_data);
+
+       if (!access_ok(VERIFY_WRITE, (void *)buff, count))
+               return -EFAULT;
+
+       if (minor == SHUTDOWN_BTN_MINOR) {
+               if (landisk_btn & 0x10) {
+                       put_user(1, buff);
+                       return 1;
+               } else {
+                       return 0;
+               }
+       }
+       return 0;
+}
+
+static int swdrv_write(struct file *filp, const char *buff, size_t count,
+                      loff_t * ppos)
+{
+       int minor;
+       minor = (int)(filp->private_data);
+
+       if (minor == SHUTDOWN_BTN_MINOR) {
+               return count;
+       }
+       return count;
+}
+
+static irqreturn_t sw_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       landisk_btn = (0x0ff & (~ctrl_inb(PA_STATUS)));
+       disable_irq(IRQ_BUTTON);
+       disable_irq(IRQ_POWER);
+       ctrl_outb(0x00, PA_PWRINT_CLR);
+
+       if (landisk_btnctrlpid != 0) {
+               kill_proc(landisk_btnctrlpid, SIGUSR1, 1);
+               landisk_btnctrlpid = 0;
+       }
+
+       return IRQ_HANDLED;
+}
+
+static struct file_operations swdrv_fops = {
+       .read = swdrv_read,     /* read */
+       .write = swdrv_write,   /* write */
+       .open = swdrv_open,     /* open */
+       .release = swdrv_close, /* release */
+       .ioctl = gio_ioctl,     /* ioctl */
+
+};
+
+static char banner[] __initdata =
+    KERN_INFO "LANDISK and USL-5P Button, LED and GIO driver initialized\n";
+
+int __init swdrv_init(void)
+{
+       int error;
+
+       printk("%s", banner);
+
+       openCnt = 0;
+       openCntLED = 0;
+       openCntBtn = 0;
+       openCntGio = 0;
+       landisk_btn = 0;
+       landisk_btnctrlpid = 0;
+
+       if ((error = register_chrdev(SHUTDOWN_BTN_MAJOR, "swdrv", &swdrv_fops))) {
+               printk(KERN_ERR
+                      "Button, LED and GIO driver:Couldn't register driver, error=%d\n",
+                      error);
+               return 1;
+       }
+
+       if (request_irq(IRQ_POWER, sw_interrupt, 0, "SHUTDOWNSWITCH", NULL)) {
+               printk(KERN_ERR "Unable to get IRQ 11.\n");
+               return 1;
+       }
+       if (request_irq(IRQ_BUTTON, sw_interrupt, 0, "USL-5P BUTTON", NULL)) {
+               printk(KERN_ERR "Unable to get IRQ 12.\n");
+               return 1;
+       }
+       ctrl_outb(0x00, PA_PWRINT_CLR);
+
+       return 0;
+}
+
+module_init(swdrv_init);
+
+/*
+ * gio driver
+ *
+ */
+
+#include <asm/landisk/gio.h>
+
+static int gio_ioctl(struct inode *inode, struct file *filp,
+                    unsigned int cmd, unsigned long arg)
+{
+       int minor;
+       unsigned int data, mask;
+       static unsigned int addr = 0;
+
+       minor = (int)(filp->private_data);
+
+       /* access control */
+       if (minor == GIO_MINOR) {
+               ;
+       } else if (minor == LED_MINOR) {
+               if (((cmd & 0x0ff) >= 9) && ((cmd & 0x0ff) < 20)) {
+                       ;
+               } else {
+                       return -EINVAL;
+               }
+       } else if (minor == BTN_MINOR) {
+               if (((cmd & 0x0ff) >= 20) && ((cmd & 0x0ff) < 30)) {
+                       ;
+               } else {
+                       return -EINVAL;
+               }
+       } else {
+               return -EINVAL;
+       }
+
+       if (cmd & 0x01) {       /* write */
+               if (copy_from_user(&data, (int *)arg, sizeof(int))) {
+                       return -EFAULT;
+               }
+       }
+
+       switch (cmd) {
+       case GIODRV_IOCSGIOSETADDR:     /* addres set */
+               addr = data;
+               break;
+
+       case GIODRV_IOCSGIODATA1:       /* write byte */
+               ctrl_outb((unsigned char)(0x0ff & data), addr);
+               break;
+
+       case GIODRV_IOCSGIODATA2:       /* write word */
+               if (addr & 0x01) {
+                       return -EFAULT;
+               }
+               ctrl_outw((unsigned short int)(0x0ffff & data), addr);
+               break;
+
+       case GIODRV_IOCSGIODATA4:       /* write long */
+               if (addr & 0x03) {
+                       return -EFAULT;
+               }
+               ctrl_outl(data, addr);
+               break;
+
+       case GIODRV_IOCGGIODATA1:       /* read byte */
+               data = ctrl_inb(addr);
+               break;
+
+       case GIODRV_IOCGGIODATA2:       /* read word */
+               if (addr & 0x01) {
+                       return -EFAULT;
+               }
+               data = ctrl_inw(addr);
+               break;
+
+       case GIODRV_IOCGGIODATA4:       /* read long */
+               if (addr & 0x03) {
+                       return -EFAULT;
+               }
+               data = ctrl_inl(addr);
+               break;
+       case GIODRV_IOCSGIO_LED:        /* write */
+               mask = ((data & 0x00ffffff) << 8)
+                   | ((data & 0x0000ffff) << 16)
+                   | ((data & 0x000000ff) << 24);
+               landisk_ledparam = data & (~mask);
+               if (landisk_arch == 0) {        /* arch == landisk */
+                       landisk_ledparam &= 0x03030303;
+                       mask = (~(landisk_ledparam >> 22)) & 0x000c;
+                       landisk_ledparam |= mask;
+               } else {                        /* arch == usl-5p */
+                       mask = (landisk_ledparam >> 24) & 0x0001;
+                       landisk_ledparam |= mask;
+                       landisk_ledparam &= 0x007f7f7f;
+               }
+               landisk_ledparam |= 0x80;
+               break;
+       case GIODRV_IOCGGIO_LED:        /* read */
+               data = landisk_ledparam;
+               if (landisk_arch == 0) {        /* arch == landisk */
+                       data &= 0x03030303;
+               } else {                        /* arch == usl-5p */
+                       ;
+               }
+               data &= (~0x080);
+               break;
+       case GIODRV_IOCSGIO_BUZZER:     /* write */
+               landisk_buzzerparam = data;
+               landisk_ledparam |= 0x80;
+               break;
+       case GIODRV_IOCGGIO_LANDISK:    /* read */
+               data = landisk_arch & 0x01;
+               break;
+       case GIODRV_IOCGGIO_BTN:        /* read */
+               data = (0x0ff & ctrl_inb(PA_PWRINT_CLR));
+               data <<= 8;
+               data |= (0x0ff & ctrl_inb(PA_IMASK));
+               data <<= 8;
+               data |= (0x0ff & landisk_btn);
+               data <<= 8;
+               data |= (0x0ff & (~ctrl_inb(PA_STATUS)));
+               break;
+       case GIODRV_IOCSGIO_BTNPID:     /* write */
+               landisk_btnctrlpid = data;
+               landisk_btn = 0;
+               if (irq_desc[IRQ_BUTTON].depth) {
+                       enable_irq(IRQ_BUTTON);
+               }
+               if (irq_desc[IRQ_POWER].depth) {
+                       enable_irq(IRQ_POWER);
+               }
+               break;
+       case GIODRV_IOCGGIO_BTNPID:     /* read */
+               data = landisk_btnctrlpid;
+               break;
+       default:
+               return -EFAULT;
+               break;
+       }
+
+       if ((cmd & 0x01) == 0) {        /* read */
+               if (copy_to_user((int *)arg, &data, sizeof(int))) {
+                       return -EFAULT;
+               }
+       }
+       return 0;
+}
diff --git a/arch/sh/boards/landisk/rtc.c b/arch/sh/boards/landisk/rtc.c
new file mode 100644 (file)
index 0000000..35ba726
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * arch/sh/boards/landisk/rtc.c --  RTC support
+ *
+ *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
+ *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
+ */
+/*
+ * modifed by kogiidena
+ * 2005.09.16
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/bcd.h>
+#include <asm/rtc.h>
+
+extern spinlock_t rtc_lock;
+
+extern void
+rs5c313_set_cmos_time(unsigned int BCD_yr, unsigned int BCD_mon,
+                     unsigned int BCD_day, unsigned int BCD_hr,
+                     unsigned int BCD_min, unsigned int BCD_sec);
+
+extern unsigned long
+rs5c313_get_cmos_time(unsigned int *BCD_yr, unsigned int *BCD_mon,
+                     unsigned int *BCD_day, unsigned int *BCD_hr,
+                     unsigned int *BCD_min, unsigned int *BCD_sec);
+
+void landisk_rtc_gettimeofday(struct timespec *tv)
+{
+       unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
+       unsigned long flags;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+       tv->tv_sec = rs5c313_get_cmos_time
+           (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
+       tv->tv_nsec = 0;
+       spin_unlock_irqrestore(&rtc_lock, flags);
+}
+
+int landisk_rtc_settimeofday(const time_t secs)
+{
+       int retval = 0;
+       int real_seconds, real_minutes, cmos_minutes;
+       unsigned long flags;
+       unsigned long nowtime = secs;
+       unsigned int BCD_yr, BCD_mon, BCD_day, BCD_hr, BCD_min, BCD_sec;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+
+       rs5c313_get_cmos_time
+         (&BCD_yr, &BCD_mon, &BCD_day, &BCD_hr, &BCD_min, &BCD_sec);
+       cmos_minutes = BCD_min;
+       BCD_TO_BIN(cmos_minutes);
+
+       /*
+        * since we're only adjusting minutes and seconds,
+        * don't interfere with hour overflow. This avoids
+        * messing with unknown time zones but requires your
+        * RTC not to be off by more than 15 minutes
+        */
+       real_seconds = nowtime % 60;
+       real_minutes = nowtime / 60;
+       if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
+               real_minutes += 30;     /* correct for half hour time zone */
+       real_minutes %= 60;
+
+       if (abs(real_minutes - cmos_minutes) < 30) {
+               BIN_TO_BCD(real_seconds);
+               BIN_TO_BCD(real_minutes);
+               rs5c313_set_cmos_time(BCD_yr, BCD_mon, BCD_day, BCD_hr,
+                                     real_minutes, real_seconds);
+       } else {
+               printk(KERN_WARNING
+                      "set_rtc_time: can't update from %d to %d\n",
+                      cmos_minutes, real_minutes);
+               retval = -1;
+       }
+
+       spin_unlock_irqrestore(&rtc_lock, flags);
+       return retval;
+}
+
+void landisk_time_init(void)
+{
+       rtc_sh_get_time = landisk_rtc_gettimeofday;
+       rtc_sh_set_time = landisk_rtc_settimeofday;
+}
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
new file mode 100644 (file)
index 0000000..127b9e0
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * arch/sh/boards/landisk/setup.c
+ *
+ * Copyright (C) 2000 Kazumoto Kojima
+ * Copyright (C) 2002 Paul Mundt
+ *
+ * I-O DATA Device, Inc. LANDISK Support.
+ *
+ * Modified for LANDISK by
+ * Atom Create Engineering Co., Ltd. 2002.
+ *
+ * modifed by kogiidena
+ * 2005.09.16
+ *
+ * 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/config.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/mm.h>
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/landisk/iodata_landisk.h>
+#include <asm/io.h>
+
+void landisk_time_init(void);
+void init_landisk_IRQ(void);
+
+int landisk_ledparam;
+int landisk_buzzerparam;
+int landisk_arch;
+
+/* cycle the led's in the clasic knightrider/sun pattern */
+static void heartbeat_landisk(void)
+{
+       static unsigned int cnt = 0, blink = 0x00, period = 25;
+        volatile u8 *p = (volatile u8 *)PA_LED;
+       char data;
+
+        if ((landisk_ledparam & 0x080) == 0)
+               return;
+
+       cnt += 1;
+
+        if (cnt < period)
+               return;
+
+       cnt = 0;
+       blink++;
+
+       data = (blink & 0x01) ? (landisk_ledparam >> 16) : 0;
+       data |= (blink & 0x02) ? (landisk_ledparam >> 8) : 0;
+       data |= landisk_ledparam;
+
+       /* buzzer */
+       if (landisk_buzzerparam & 0x1) {
+               data |= 0x80;
+       } else {
+               data &= 0x7f;
+       }
+       *p = data;
+
+        if (((landisk_ledparam & 0x007f7f00) == 0) &&
+             (landisk_buzzerparam == 0))
+               landisk_ledparam &= (~0x0080);
+
+       landisk_buzzerparam >>= 1;
+}
+
+static void landisk_power_off(void)
+{
+        ctrl_outb(0x01, PA_SHUTDOWN);
+}
+
+static void check_usl5p(void)
+{
+        volatile u8 *p = (volatile u8 *)PA_LED;
+        u8 tmp1, tmp2;
+
+        tmp1 = *p;
+        *p = 0x40;
+        tmp2 = *p;
+        *p = tmp1;
+
+        landisk_arch = (tmp2 == 0x40);
+        if (landisk_arch == 1) {
+                /* arch == usl-5p */
+                landisk_ledparam = 0x00000380;
+                landisk_ledparam |= (tmp1 & 0x07c);
+        } else {
+                /* arch == landisk */
+                landisk_ledparam = 0x02000180;
+                landisk_ledparam |= 0x04;
+        }
+}
+
+void *area5_io_base;
+void *area6_io_base;
+
+static int __init landisk_cf_init(void)
+{
+       pgprot_t prot;
+       unsigned long paddrbase, psize;
+
+       /* open I/O area window */
+       paddrbase = virt_to_phys((void *)PA_AREA5_IO);
+       psize = PAGE_SIZE;
+       prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_IO16);
+       area5_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+       if (!area5_io_base) {
+               printk("allocate_cf_area : can't open CF I/O window!\n");
+               return -ENOMEM;
+       }
+
+       paddrbase = virt_to_phys((void *)PA_AREA6_IO);
+       psize = PAGE_SIZE;
+       prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO16);
+       area6_io_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+       if (!area6_io_base) {
+               printk("allocate_cf_area : can't open HDD I/O window!\n");
+               return -ENOMEM;
+       }
+
+       printk(KERN_INFO "Allocate Area5/6 success.\n");
+
+       /* XXX : do we need attribute and common-memory area also? */
+
+       return 0;
+}
+
+static void __init landisk_setup(char **cmdline_p)
+{
+       device_initcall(landisk_cf_init);
+
+       landisk_buzzerparam = 0;
+       check_usl5p();
+
+       printk(KERN_INFO "I-O DATA DEVICE, INC. \"LANDISK Series\" support.\n");
+
+       board_time_init = landisk_time_init;
+       pm_power_off = landisk_power_off;
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_landisk __initmv = {
+       .mv_name = "LANDISK",
+       .mv_setup = landisk_setup,
+       .mv_nr_irqs = 72,
+       .mv_inb = landisk_inb,
+       .mv_inw = landisk_inw,
+       .mv_inl = landisk_inl,
+       .mv_outb = landisk_outb,
+       .mv_outw = landisk_outw,
+       .mv_outl = landisk_outl,
+       .mv_inb_p = landisk_inb_p,
+       .mv_inw_p = landisk_inw,
+       .mv_inl_p = landisk_inl,
+       .mv_outb_p = landisk_outb_p,
+       .mv_outw_p = landisk_outw,
+       .mv_outl_p = landisk_outl,
+       .mv_insb = landisk_insb,
+       .mv_insw = landisk_insw,
+       .mv_insl = landisk_insl,
+       .mv_outsb = landisk_outsb,
+       .mv_outsw = landisk_outsw,
+       .mv_outsl = landisk_outsl,
+       .mv_ioport_map = landisk_ioport_map,
+       .mv_init_irq = init_landisk_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat = heartbeat_landisk,
+#endif
+};
+ALIAS_MV(landisk)
index a76c655dceeeba4790a2654b03e525f824bf24ee..03b123a4bba42d54bd2757dc514da30fe1f7a998 100644 (file)
@@ -130,7 +130,7 @@ int mpc1211_rtc_settimeofday(const struct timeval *tv)
 
 void mpc1211_time_init(void)
 {
-       rtc_get_time = mpc1211_rtc_gettimeofday;
-       rtc_set_time = mpc1211_rtc_settimeofday;
+       rtc_sh_get_time = mpc1211_rtc_gettimeofday;
+       rtc_sh_set_time = mpc1211_rtc_settimeofday;
 }
 
index 2bfb221cc35cbfd75890d0ceaae3f9e0a3a7409d..8eb5d430397257f0884400a5e6abc2ee72d915ec 100644 (file)
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/interrupt.h>
-
 #include <asm/io.h>
 #include <asm/machvec.h>
 #include <asm/mpc1211/mpc1211.h>
 #include <asm/mpc1211/pci.h>
 #include <asm/mpc1211/m1543c.h>
 
-
 /* ALI15X3 SMBus address offsets */
 #define SMBHSTSTS   (0 + 0x3100)
 #define SMBHSTCNT   (1 + 0x3100)
 #define ALI15X3_STS_TERM       0x80    /* terminated by abort */
 #define ALI15X3_STS_ERR                0xE0    /* all the bad error bits */
 
-const char *get_system_type(void)
-{
-       return "Interface MPC-1211(CTP/PCI/MPC-SH02)";
-}
-
 static void __init pci_write_config(unsigned long busNo,
                                    unsigned long devNo,
                                    unsigned long fncNo,
@@ -80,9 +73,6 @@ volatile unsigned long irq_err_count;
 
 static void disable_mpc1211_irq(unsigned int irq)
 {
-       unsigned long flags;
-
-       save_and_cli(flags);
        if( irq < 8) {
                m_irq_mask |= (1 << irq);
                outb(m_irq_mask,I8259_M_MR);
@@ -90,16 +80,11 @@ static void disable_mpc1211_irq(unsigned int irq)
                s_irq_mask |= (1 << (irq - 8));
                outb(s_irq_mask,I8259_S_MR);
        }
-       restore_flags(flags);
 
 }
 
 static void enable_mpc1211_irq(unsigned int irq)
 {
-       unsigned long flags;
-
-       save_and_cli(flags);
-
        if( irq < 8) {
                m_irq_mask &= ~(1 << irq);
                outb(m_irq_mask,I8259_M_MR);
@@ -107,7 +92,6 @@ static void enable_mpc1211_irq(unsigned int irq)
                s_irq_mask &= ~(1 << (irq - 8));
                outb(s_irq_mask,I8259_S_MR);
        }
-       restore_flags(flags);
 }
 
 static inline int mpc1211_irq_real(unsigned int irq)
@@ -131,10 +115,6 @@ static inline int mpc1211_irq_real(unsigned int irq)
 
 static void mask_and_ack_mpc1211(unsigned int irq)
 {
-       unsigned long flags;
-
-       save_and_cli(flags);
-
        if(irq < 8) {
                if(m_irq_mask & (1<<irq)){
                  if(!mpc1211_irq_real(irq)){
@@ -162,7 +142,6 @@ static void mask_and_ack_mpc1211(unsigned int irq)
                outb(0x60+(irq-8),I8259_S_CR);  /* EOI */
                outb(0x60+2,I8259_M_CR);
        }
-       restore_flags(flags);
 }
 
 static void end_mpc1211_irq(unsigned int irq)
@@ -219,7 +198,7 @@ int mpc1211_irq_demux(int irq)
        return irq;
 }
 
-void __init init_mpc1211_IRQ(void)
+static void __init init_mpc1211_IRQ(void)
 {
        int i;
        /*
@@ -255,23 +234,12 @@ void __init init_mpc1211_IRQ(void)
        }
 }
 
-/*
-  Initialize the board
-*/
-
-
-static void delay (void)
-{
-       volatile unsigned short tmp;
-       tmp = *(volatile unsigned short *) 0xa0000000;
-}
-
-static void delay1000 (void)
+static void delay1000(void)
 {
        int i;
 
        for (i=0; i<1000; i++)
-               delay ();
+               ctrl_delay();
 }
 
 static int put_smb_blk(unsigned char *p, int address, int command, int no)
@@ -314,26 +282,10 @@ static int put_smb_blk(unsigned char *p, int address, int command, int no)
        return 0;
 }
 
-/*
- * The Machine Vector
- */
-
-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)
-
 /* arch/sh/boards/mpc1211/rtc.c */
 void mpc1211_time_init(void);
 
-int __init platform_setup(void)
+static void __init mpc1211_setup(char **cmdline_p)
 {
        unsigned char spd_buf[128];
 
@@ -357,3 +309,18 @@ int __init platform_setup(void)
        return 0;
 }
 
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_mpc1211 __initmv = {
+       .mv_name                = "Interface MPC-1211(CTP/PCI/MPC-SH02)",
+       .mv_setup               = mpc1211_setup,
+       .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)
diff --git a/arch/sh/boards/overdrive/Makefile b/arch/sh/boards/overdrive/Makefile
deleted file mode 100644 (file)
index 245f03b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the STMicroelectronics Overdrive specific parts of the kernel
-#
-
-obj-y   := mach.o setup.o io.o irq.o led.o
-
-obj-$(CONFIG_PCI) += fpga.o galileo.o pcidma.o
-
diff --git a/arch/sh/boards/overdrive/fpga.c b/arch/sh/boards/overdrive/fpga.c
deleted file mode 100644 (file)
index 956c239..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * This file handles programming up the Altera Flex10K that interfaces to
- * the Galileo, and does the PS/2 keyboard and mouse
- *
- */
-
-
-#include <linux/kernel.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-
-
-#include <asm/overdriver/gt64111.h>
-#include <asm/overdrive/overdrive.h>
-#include <asm/overdrive/fpga.h>
-
-#define FPGA_NotConfigHigh()  (*FPGA_ControlReg) = (*FPGA_ControlReg) | ENABLE_FPGA_BIT
-#define FPGA_NotConfigLow()   (*FPGA_ControlReg) = (*FPGA_ControlReg) & RESET_FPGA_MASK
-
-/* I need to find out what (if any) the real delay factor here is */
-/* The delay is definately not critical */
-#define long_delay() {int i;for(i=0;i<10000;i++);}
-#define short_delay() {int i;for(i=0;i<100;i++);}
-
-static void __init program_overdrive_fpga(const unsigned char *fpgacode,
-                                         int size)
-{
-       int timeout = 0;
-       int i, j;
-       unsigned char b;
-       static volatile unsigned char *FPGA_ControlReg =
-           (volatile unsigned char *) (OVERDRIVE_CTRL);
-       static volatile unsigned char *FPGA_ProgramReg =
-           (volatile unsigned char *) (FPGA_DCLK_ADDRESS);
-
-       printk("FPGA:  Commencing FPGA Programming\n");
-
-       /* The PCI reset but MUST be low when programming the FPGA !!! */
-       b = (*FPGA_ControlReg) & RESET_PCI_MASK;
-
-       (*FPGA_ControlReg) = b;
-
-       /* Prepare FPGA to program */
-
-       FPGA_NotConfigHigh();
-       long_delay();
-
-       FPGA_NotConfigLow();
-       short_delay();
-
-       while ((*FPGA_ProgramReg & FPGA_NOT_STATUS) != 0) {
-               printk("FPGA:  Waiting for NotStatus to go Low ... \n");
-       }
-
-       FPGA_NotConfigHigh();
-
-       /* Wait for FPGA "ready to be programmed" signal */
-       printk("FPGA:  Waiting for NotStatus to go high (FPGA ready)... \n");
-
-       for (timeout = 0;
-            (((*FPGA_ProgramReg & FPGA_NOT_STATUS) == 0)
-             && (timeout < FPGA_TIMEOUT)); timeout++);
-
-       /* Check if timeout condition occured - i.e. an error */
-
-       if (timeout == FPGA_TIMEOUT) {
-               printk
-                   ("FPGA:  Failed to program - Timeout waiting for notSTATUS to go high\n");
-               return;
-       }
-
-       printk("FPGA:  Copying data to FPGA ... %d bytes\n", size);
-
-       /* Copy array to FPGA - bit at a time */
-
-       for (i = 0; i < size; i++) {
-               volatile unsigned w = 0;
-
-               for (j = 0; j < 8; j++) {
-                       *FPGA_ProgramReg = (fpgacode[i] >> j) & 0x01;
-                       short_delay();
-               }
-               if ((i & 0x3ff) == 0) {
-                       printk(".");
-               }
-       }
-
-       /* Waiting for CONFDONE to go high - means the program is complete  */
-
-       for (timeout = 0;
-            (((*FPGA_ProgramReg & FPGA_CONFDONE) == 0)
-             && (timeout < FPGA_TIMEOUT)); timeout++) {
-
-               *FPGA_ProgramReg = 0x0;
-               long_delay();
-       }
-
-       if (timeout == FPGA_TIMEOUT) {
-               printk
-                   ("FPGA:  Failed to program - Timeout waiting for CONFDONE to go high\n");
-               return;
-       } else {                /* Clock another 10 times - gets the device into a working state      */
-               for (i = 0; i < 10; i++) {
-                       *FPGA_ProgramReg = 0x0;
-                       short_delay();
-               }
-       }
-
-       printk("FPGA:  Programming complete\n");
-}
-
-
-static const unsigned char __init fpgacode[] = {
-#include "./overdrive.ttf"     /* Code from maxplus2 compiler */
-       , 0, 0
-};
-
-
-int __init init_overdrive_fpga(void)
-{
-       program_overdrive_fpga(fpgacode, sizeof(fpgacode));
-
-       return 0;
-}
diff --git a/arch/sh/boards/overdrive/galileo.c b/arch/sh/boards/overdrive/galileo.c
deleted file mode 100644 (file)
index 29e4897..0000000
+++ /dev/null
@@ -1,587 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@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 the PCI routines required for the Galileo GT6411 
- * PCI bridge as used on the Orion and Overdrive boards.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/ioport.h>
-
-#include <asm/overdrive/overdrive.h>
-#include <asm/overdrive/gt64111.h>
-
-
-/* After boot, we shift the Galileo registers so that they appear 
- * in BANK6, along with IO space. This means we can have one contingous
- * lump of PCI address space without these registers appearing in the 
- * middle of them 
- */
-
-#define GT64111_BASE_ADDRESS  0xbb000000
-#define GT64111_IO_BASE_ADDRESS  0x1000
-/* The GT64111 registers appear at this address to the SH4 after reset */
-#define RESET_GT64111_BASE_ADDRESS           0xb4000000
-
-/* Macros used to access the Galileo registers */
-#define RESET_GT64111_REG(x) (RESET_GT64111_BASE_ADDRESS+x)
-#define GT64111_REG(x) (GT64111_BASE_ADDRESS+x)
-
-#define RESET_GT_WRITE(x,v) writel((v),RESET_GT64111_REG(x))
-
-#define RESET_GT_READ(x) readl(RESET_GT64111_REG(x))
-
-#define GT_WRITE(x,v) writel((v),GT64111_REG(x))
-#define GT_WRITE_BYTE(x,v) writeb((v),GT64111_REG(x))
-#define GT_WRITE_SHORT(x,v) writew((v),GT64111_REG(x))
-
-#define GT_READ(x)    readl(GT64111_REG(x))
-#define GT_READ_BYTE(x)  readb(GT64111_REG(x))
-#define GT_READ_SHORT(x) readw(GT64111_REG(x))
-
-
-/* Where the various SH banks start at */
-#define SH_BANK4_ADR 0xb0000000
-#define SH_BANK5_ADR 0xb4000000
-#define SH_BANK6_ADR 0xb8000000
-
-/* Masks out everything but lines 28,27,26 */
-#define BANK_SELECT_MASK 0x1c000000
-
-#define SH4_TO_BANK(x) ( (x) & BANK_SELECT_MASK)
-
-/* 
- * Masks used for address conversaion. Bank 6 is used for IO and 
- * has all the address bits zeroed by the FPGA. Special case this
- */
-#define MEMORY_BANK_MASK 0x1fffffff
-#define IO_BANK_MASK  0x03ffffff
-
-/* Mark bank 6 as the bank used for IO. You can change this in the FPGA code
- * if you want 
- */
-#define IO_BANK_ADR PCI_GTIO_BASE
-
-/* Will select the correct mask to apply depending on the SH$ address */
-#define SELECT_BANK_MASK(x) \
-   ( (SH4_TO_BANK(x)==SH4_TO_BANK(IO_BANK_ADR)) ? IO_BANK_MASK : MEMORY_BANK_MASK)
-
-/* Converts between PCI space and P2 region */
-#define SH4_TO_PCI(x) ((x)&SELECT_BANK_MASK(x))
-
-/* Various macros for figuring out what to stick in the Galileo registers. 
- * You *really* don't want to figure this stuff out by hand, you always get
- * it wrong
- */
-#define GT_MEM_LO_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7ff)
-#define GT_MEM_HI_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>21)&0x7f)
-#define GT_MEM_SUB_ADR(x) ((((unsigned)((x)&SELECT_BANK_MASK(x)))>>20)&0xff)
-
-#define PROGRAM_HI_LO(block,a,s) \
-    GT_WRITE(block##_LO_DEC_ADR,GT_MEM_LO_ADR(a));\
-    GT_WRITE(block##_HI_DEC_ADR,GT_MEM_HI_ADR(a+s-1))
-
-#define PROGRAM_SUB_HI_LO(block,a,s) \
-    GT_WRITE(block##_LO_DEC_ADR,GT_MEM_SUB_ADR(a));\
-    GT_WRITE(block##_HI_DEC_ADR,GT_MEM_SUB_ADR(a+s-1))
-
-/* We need to set the size, and the offset register */
-
-#define GT_BAR_MASK(x) ((x)&~0xfff)
-
-/* Macro to set up the BAR in the Galileo. Essentially used for the DRAM */
-#define PROGRAM_GT_BAR(block,a,s) \
-  GT_WRITE(PCI_##block##_BANK_SIZE,GT_BAR_MASK((s-1)));\
-  write_config_to_galileo(PCI_CONFIG_##block##_BASE_ADR,\
-                            GT_BAR_MASK(a))
-
-#define DISABLE_GT_BAR(block) \
-  GT_WRITE(PCI_##block##_BANK_SIZE,0),\
-  GT_CONFIG_WRITE(PCI_CONFIG_##block##_BASE_ADR,\
-    0x80000000)
-
-/* Macros to disable things we are not going to use */
-#define DISABLE_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0x7ff);\
-                          GT_WRITE(x##_HI_DEC_ADR,0x00)
-
-#define DISABLE_SUB_DECODE(x) GT_WRITE(x##_LO_DEC_ADR,0xff);\
-                              GT_WRITE(x##_HI_DEC_ADR,0x00)
-
-static void __init reset_pci(void)
-{
-       /* Set RESET_PCI bit high */
-       writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
-       udelay(250);
-
-       /* Set RESET_PCI bit low */
-       writeb(readb(OVERDRIVE_CTRL) & RESET_PCI_MASK, OVERDRIVE_CTRL);
-       udelay(250);
-
-       writeb(readb(OVERDRIVE_CTRL) | ENABLE_PCI_BIT, OVERDRIVE_CTRL);
-       udelay(250);
-}
-
-static int write_config_to_galileo(int where, u32 val);
-#define GT_CONFIG_WRITE(where,val) write_config_to_galileo(where,val)
-
-#define ENABLE_PCI_DRAM
-
-
-#ifdef TEST_DRAM
-/* Test function to check out if the PCI DRAM is working OK */
-static int  /* __init */ test_dram(unsigned *base, unsigned size)
-{
-       unsigned *p = base;
-       unsigned *end = (unsigned *) (((unsigned) base) + size);
-       unsigned w;
-
-       for (p = base; p < end; p++) {
-               *p = 0xffffffff;
-               if (*p != 0xffffffff) {
-                       printk("AAARGH -write failed!!! at %p is %x\n", p,
-                              *p);
-                       return 0;
-               }
-               *p = 0x0;
-               if (*p != 0x0) {
-                       printk("AAARGH -write failed!!!\n");
-                       return 0;
-               }
-       }
-
-       for (p = base; p < end; p++) {
-               *p = (unsigned) p;
-               if (*p != (unsigned) p) {
-                       printk("Failed at 0x%p, actually is 0x%x\n", p,
-                              *p);
-                       return 0;
-               }
-       }
-
-       for (p = base; p < end; p++) {
-               w = ((unsigned) p & 0xffff0000);
-               *p = w | (w >> 16);
-       }
-
-       for (p = base; p < end; p++) {
-               w = ((unsigned) p & 0xffff0000);
-               w |= (w >> 16);
-               if (*p != w) {
-                       printk
-                           ("Failed at 0x%p, should be 0x%x actually is 0x%x\n",
-                            p, w, *p);
-                       return 0;
-               }
-       }
-
-       return 1;
-}
-#endif
-
-
-/* Function to set up and initialise the galileo. This sets up the BARS,
- * maps the DRAM into the address space etc,etc
- */
-int __init galileo_init(void)
-{
-       reset_pci();
-
-       /* Now shift the galileo regs into this block */
-       RESET_GT_WRITE(INTERNAL_SPACE_DEC,
-                      GT_MEM_LO_ADR(GT64111_BASE_ADDRESS));
-
-       /* Should have a sanity check here, that you can read back  at the new
-        * address what you just wrote 
-        */
-
-       /* Disable decode for all regions */
-       DISABLE_DECODE(RAS10);
-       DISABLE_DECODE(RAS32);
-       DISABLE_DECODE(CS20);
-       DISABLE_DECODE(CS3);
-       DISABLE_DECODE(PCI_IO);
-       DISABLE_DECODE(PCI_MEM0);
-       DISABLE_DECODE(PCI_MEM1);
-
-       /* Disable all BARS */
-       GT_WRITE(BAR_ENABLE_ADR, 0x1ff);
-       DISABLE_GT_BAR(RAS10);
-       DISABLE_GT_BAR(RAS32);
-       DISABLE_GT_BAR(CS20);
-       DISABLE_GT_BAR(CS3);
-
-       /* Tell the BAR where the IO registers now are */
-       GT_CONFIG_WRITE(PCI_CONFIG_INT_REG_IO_ADR,GT_BAR_MASK(
-                                           (GT64111_IO_BASE_ADDRESS &
-                                            IO_BANK_MASK)));
-       /* set up a 112 Mb decode */
-       PROGRAM_HI_LO(PCI_MEM0, SH_BANK4_ADR, 112 * 1024 * 1024);
-
-       /* Set up a 32 MB io space decode */
-       PROGRAM_HI_LO(PCI_IO, IO_BANK_ADR, 32 * 1024 * 1024);
-
-#ifdef ENABLE_PCI_DRAM
-       /* Program up the DRAM configuration - there is DRAM only in bank 0 */
-       /* Now set up the DRAM decode */
-       PROGRAM_HI_LO(RAS10, PCI_DRAM_BASE, PCI_DRAM_SIZE);
-       /* And the sub decode */
-       PROGRAM_SUB_HI_LO(RAS0, PCI_DRAM_BASE, PCI_DRAM_SIZE);
-
-       DISABLE_SUB_DECODE(RAS1);
-
-       /* Set refresh rate */
-       GT_WRITE(DRAM_BANK0_PARMS, 0x3f);
-       GT_WRITE(DRAM_CFG, 0x100);
-
-       /* we have to lob off the top bits rememeber!! */
-       PROGRAM_GT_BAR(RAS10, SH4_TO_PCI(PCI_DRAM_BASE), PCI_DRAM_SIZE);
-
-#endif
-
-       /* We are only interested in decoding RAS10 and the Galileo's internal 
-        * registers (as IO) on the PCI bus
-        */
-#ifdef ENABLE_PCI_DRAM
-       GT_WRITE(BAR_ENABLE_ADR, (~((1 << 8) | (1 << 3))) & 0x1ff);
-#else
-       GT_WRITE(BAR_ENABLE_ADR, (~(1 << 3)) & 0x1ff);
-#endif
-
-       /* Change the class code to host bridge, it actually powers up 
-        * as a memory controller
-         */
-       GT_CONFIG_WRITE(8, 0x06000011);
-
-       /* Allow the galileo to master the PCI bus */
-       GT_CONFIG_WRITE(PCI_COMMAND,
-                       PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
-                       PCI_COMMAND_IO);
-
-
-#if 0
-        printk("Testing PCI DRAM - ");
-       if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
-               printk("Passed\n");
-       }else {
-               printk("FAILED\n");
-       }
-#endif
-       return 0;
-
-}
-
-
-#define SET_CONFIG_BITS(bus,devfn,where)\
-  ((1<<31) | ((bus) << 16) | ((devfn) << 8) | ((where) & ~3))
-
-#define CONFIG_CMD(dev, where) SET_CONFIG_BITS((dev)->bus->number,(dev)->devfn,where)
-
-/* This write to the galileo config registers, unlike the functions below, can
- * be used before the PCI subsystem has started up
- */
-static int __init write_config_to_galileo(int where, u32 val)
-{
-       GT_WRITE(PCI_CFG_ADR, SET_CONFIG_BITS(0, 0, where));
-
-       GT_WRITE(PCI_CFG_DATA, val);
-       return 0;
-}
-
-/* We exclude the galileo and slot 31, the galileo because I don't know how to stop
- * the setup code shagging up the setup I have done on it, and 31 because the whole
- * thing locks up if you try to access that slot (which doesn't exist of course anyway
- */
-
-#define EXCLUDED_DEV(dev) ((dev->bus->number==0) && ((PCI_SLOT(dev->devfn)==0) || (PCI_SLOT(dev->devfn) == 31)))
-
-static int galileo_read_config_byte(struct pci_dev *dev, int where,
-                                   u8 * val)
-{
-
-        
-       /* I suspect this doesn't work because this drives a special cycle ? */
-       if (EXCLUDED_DEV(dev)) {
-               *val = 0xff;
-               return PCIBIOS_SUCCESSFUL;
-       }
-       /* Start the config cycle */
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-       /* Read back the result */
-       *val = GT_READ_BYTE(PCI_CFG_DATA + (where & 3));
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_read_config_word(struct pci_dev *dev, int where,
-                                   u16 * val)
-{
-
-        if (EXCLUDED_DEV(dev)) {
-               *val = 0xffff;
-               return PCIBIOS_SUCCESSFUL;
-       }
-
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-       *val = GT_READ_SHORT(PCI_CFG_DATA + (where & 2));
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_read_config_dword(struct pci_dev *dev, int where,
-                                    u32 * val)
-{
-       if (EXCLUDED_DEV(dev)) {
-               *val = 0xffffffff;
-               return PCIBIOS_SUCCESSFUL;
-       }
-
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-       *val = GT_READ(PCI_CFG_DATA);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_write_config_byte(struct pci_dev *dev, int where,
-                                    u8 val)
-{
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-
-       GT_WRITE_BYTE(PCI_CFG_DATA + (where & 3), val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int galileo_write_config_word(struct pci_dev *dev, int where,
-                                    u16 val)
-{
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-
-       GT_WRITE_SHORT(PCI_CFG_DATA + (where & 2), val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static int galileo_write_config_dword(struct pci_dev *dev, int where,
-                                     u32 val)
-{
-       GT_WRITE(PCI_CFG_ADR, CONFIG_CMD(dev, where));
-
-       GT_WRITE(PCI_CFG_DATA, val);
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops pci_config_ops = {
-       galileo_read_config_byte,
-       galileo_read_config_word,
-       galileo_read_config_dword,
-       galileo_write_config_byte,
-       galileo_write_config_word,
-       galileo_write_config_dword
-};
-
-
-/* Everything hangs off this */
-static struct pci_bus *pci_root_bus;
-
-
-static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
-{
-       return PCI_SLOT(dev->devfn);
-}
-
-static int __init map_od_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       /* Slot 1: Galileo 
-        * Slot 2: PCI Slot 1
-        * Slot 3: PCI Slot 2
-        * Slot 4: ESS
-        */
-       switch (slot) {
-       case 2: 
-               return OVERDRIVE_PCI_IRQ1;
-       case 3:
-               /* Note this assumes you have a hacked card in slot 2 */
-               return OVERDRIVE_PCI_IRQ2;
-       case 4:
-               return OVERDRIVE_ESS_IRQ;
-       default:
-               /* printk("PCI: Unexpected IRQ mapping request for slot %d\n", slot); */
-               return -1;
-       }
-}
-
-
-
-void __init
-pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
-{
-        ranges->io_start -= bus->resource[0]->start;
-        ranges->io_end -= bus->resource[0]->start;
-        ranges->mem_start -= bus->resource[1]->start;
-        ranges->mem_end -= bus->resource[1]->start;
-}                                                                                
-
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
-{
-       int i;
-
-       /*
-        * PCI IDE controllers use non-standard I/O port decoding, respect it.
-        */
-       if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
-               return;
-       printk("PCI: IDE base address fixup for %s\n", pci_name(d));
-       for(i=0; i<4; i++) {
-               struct resource *r = &d->resource[i];
-               if ((r->start & ~0x80) == 0x374) {
-                       r->start |= 2;
-                       r->end = r->start;
-               }
-       }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
-
-void __init pcibios_init(void)
-{
-       static struct resource galio,galmem;
-
-        /* Allocate the registers used by the Galileo */
-        galio.flags = IORESOURCE_IO;
-        galio.name  = "Galileo GT64011";
-        galmem.flags = IORESOURCE_MEM|IORESOURCE_PREFETCH;
-        galmem.name  = "Galileo GT64011 DRAM";
-
-        allocate_resource(&ioport_resource, &galio, 256,
-                   GT64111_IO_BASE_ADDRESS,GT64111_IO_BASE_ADDRESS+256, 256, NULL, NULL);
-        allocate_resource(&iomem_resource, &galmem,PCI_DRAM_SIZE,
-                   PHYSADDR(PCI_DRAM_BASE), PHYSADDR(PCI_DRAM_BASE)+PCI_DRAM_SIZE, 
-                            PCI_DRAM_SIZE, NULL, NULL);
-
-       /* ok, do the scan man */
-       pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
-
-        pci_assign_unassigned_resources();
-       pci_fixup_irqs(no_swizzle, map_od_irq);
-
-#ifdef TEST_DRAM
-        printk("Testing PCI DRAM - ");
-       if(test_dram(PCI_DRAM_BASE,PCI_DRAM_SIZE)) {
-               printk("Passed\n");
-       }else {
-               printk("FAILED\n");
-       }
-#endif
-
-}
-
-char * __init pcibios_setup(char *str)
-{
-       return str;
-}
-
-
-
-int pcibios_enable_device(struct pci_dev *dev)
-{
-
-       u16 cmd, old_cmd;
-       int idx;
-       struct resource *r;
-
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       old_cmd = cmd;
-       for (idx = 0; idx < 6; idx++) {
-               r = dev->resource + idx;
-               if (!r->start && r->end) {
-                       printk(KERN_ERR
-                              "PCI: Device %s not available because"
-                              " of resource collisions\n",
-                              pci_name(dev));
-                       return -EINVAL;
-               }
-               if (r->flags & IORESOURCE_IO)
-                       cmd |= PCI_COMMAND_IO;
-               if (r->flags & IORESOURCE_MEM)
-                       cmd |= PCI_COMMAND_MEMORY;
-       }
-       if (cmd != old_cmd) {
-               printk("PCI: enabling device %s (%04x -> %04x)\n",
-                      pci_name(dev), old_cmd, cmd);
-               pci_write_config_word(dev, PCI_COMMAND, cmd);
-       }
-       return 0;
-
-}
-
-/* We should do some optimisation work here I think. Ok for now though */
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
-
-}
-
-void pcibios_align_resource(void *data, struct resource *res,
-                           resource_size_t size)
-{
-}
-
-void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-                            struct resource *res, int resource)
-{
-
-       unsigned long where, size;
-       u32 reg;
-       
-
-       printk("PCI: Assigning %3s %08lx to %s\n",
-              res->flags & IORESOURCE_IO ? "IO" : "MEM",
-              res->start, dev->name);
-
-       where = PCI_BASE_ADDRESS_0 + resource * 4;
-       size = res->end - res->start;
-
-       pci_read_config_dword(dev, where, &reg);
-       reg = (reg & size) | (((u32) (res->start - root->start)) & ~size);
-       pci_write_config_dword(dev, where, reg);
-}
-
-
-void __init pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-       printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name);
-       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
-
-/*
- *  If we set up a device for bus mastering, we need to check the latency
- *  timer as certain crappy BIOSes forget to set it properly.
- */
-unsigned int pcibios_max_latency = 255;
-
-void pcibios_set_master(struct pci_dev *dev)
-{
-       u8 lat;
-       pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
-       if (lat < 16)
-               lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
-       else if (lat > pcibios_max_latency)
-               lat = pcibios_max_latency;
-       else
-               return;
-       printk("PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
-       pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
-}
diff --git a/arch/sh/boards/overdrive/io.c b/arch/sh/boards/overdrive/io.c
deleted file mode 100644 (file)
index 4671b6b..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@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 the I/O routines for use on the overdrive board
- *
- */
-
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/addrspace.h>
-
-#include <asm/overdrive/overdrive.h>
-
-/*
- * readX/writeX() are used to access memory mapped devices. On some
- * architectures the memory mapped IO stuff needs to be accessed
- * differently. On the SuperH architecture, we just read/write the
- * memory location directly.
- */
-
-#define dprintk(x...)
-
-/* Translates an IO address to where it is mapped in memory */
-
-#define io_addr(x) (((unsigned)(x))|PCI_GTIO_BASE)
-
-unsigned char od_inb(unsigned long port)
-{
-dprintk("od_inb(%x)\n", port);
-       return readb(io_addr(port)) & 0xff;
-}
-
-
-unsigned short od_inw(unsigned long port)
-{
-dprintk("od_inw(%x)\n", port);
-       return readw(io_addr(port)) & 0xffff;
-}
-
-unsigned int od_inl(unsigned long port)
-{
-dprintk("od_inl(%x)\n", port);
-       return readl(io_addr(port));
-}
-
-void od_outb(unsigned char value, unsigned long port)
-{
-dprintk("od_outb(%x, %x)\n", value, port);
-       writeb(value, io_addr(port));
-}
-
-void od_outw(unsigned short value, unsigned long port)
-{
-dprintk("od_outw(%x, %x)\n", value, port);
-       writew(value, io_addr(port));
-}
-
-void od_outl(unsigned int value, unsigned long port)
-{
-dprintk("od_outl(%x, %x)\n", value, port);
-       writel(value, io_addr(port));
-}
-
-/* This is horrible at the moment - needs more work to do something sensible */
-#define IO_DELAY() udelay(10)
-
-#define OUT_DELAY(x,type) \
-void od_out##x##_p(unsigned type value,unsigned long port){out##x(value,port);IO_DELAY();}
-
-#define IN_DELAY(x,type) \
-unsigned type od_in##x##_p(unsigned long port) {unsigned type tmp=in##x(port);IO_DELAY();return tmp;}
-
-
-OUT_DELAY(b,char)
-OUT_DELAY(w,short)
-OUT_DELAY(l,int)
-
-IN_DELAY(b,char)
-IN_DELAY(w,short)
-IN_DELAY(l,int)
-
-
-/*  Now for the string version of these functions */
-void od_outsb(unsigned long port, const void *addr, unsigned long count)
-{
-       int i;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p++) {
-               outb(*p, port);
-       }
-}
-
-
-void od_insb(unsigned long port, void *addr, unsigned long count)
-{
-       int i;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p++) {
-               *p = inb(port);
-       }
-}
-
-/* For the 16 and 32 bit string functions, we have to worry about alignment.
- * The SH does not do unaligned accesses, so we have to read as bytes and
- * then write as a word or dword. 
- * This can be optimised a lot more, especially in the case where the data
- * is aligned
- */
-
-void od_outsw(unsigned long port, const void *addr, unsigned long count)
-{
-       int i;
-       unsigned short tmp;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p += 2) {
-               tmp = (*p) | ((*(p + 1)) << 8);
-               outw(tmp, port);
-       }
-}
-
-
-void od_insw(unsigned long port, void *addr, unsigned long count)
-{
-       int i;
-       unsigned short tmp;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p += 2) {
-               tmp = inw(port);
-               p[0] = tmp & 0xff;
-               p[1] = (tmp >> 8) & 0xff;
-       }
-}
-
-
-void od_outsl(unsigned long port, const void *addr, unsigned long count)
-{
-       int i;
-       unsigned tmp;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p += 4) {
-               tmp = (*p) | ((*(p + 1)) << 8) | ((*(p + 2)) << 16) |
-                     ((*(p + 3)) << 24);
-               outl(tmp, port);
-       }
-}
-
-
-void od_insl(unsigned long port, void *addr, unsigned long count)
-{
-       int i;
-       unsigned tmp;
-       unsigned char *p = (unsigned char *) addr;
-
-       for (i = 0; i < count; i++, p += 4) {
-               tmp = inl(port);
-               p[0] = tmp & 0xff;
-               p[1] = (tmp >> 8) & 0xff;
-               p[2] = (tmp >> 16) & 0xff;
-               p[3] = (tmp >> 24) & 0xff;
-
-       }
-}
diff --git a/arch/sh/boards/overdrive/irq.c b/arch/sh/boards/overdrive/irq.c
deleted file mode 100644 (file)
index 5d730c7..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * Looks after interrupts on the overdrive board.
- *
- * Bases on the IPR irq system
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include <asm/overdrive/overdrive.h>
-
-struct od_data {
-       int overdrive_irq;
-       int irq_mask;
-};
-
-#define NUM_EXTERNAL_IRQS 16
-#define EXTERNAL_IRQ_NOT_IN_USE (-1)
-#define EXTERNAL_IRQ_NOT_ASSIGNED (-1)
-
-/*
- * This table is used to determine what to program into the FPGA's CT register
- * for the specified Linux IRQ.
- *
- * The irq_mask gives the interrupt number from the PCI board (PCI_Int(6:0))
- * but is one greater than that because the because the FPGA treats 0
- * as disabled, a value of 1 asserts PCI_Int0, and so on.
- *
- * The overdrive_irq specifies which of the eight interrupt sources generates
- * that interrupt, and but is multiplied by four to give the bit offset into
- * the CT register.
- *
- * The seven interrupts levels (SH4 IRL's) we have available here is hardwired
- * by the EPLD. The assignments here of which PCI interrupt generates each
- * level is arbitary.
- */
-static struct od_data od_data_table[NUM_EXTERNAL_IRQS] = {
-       /*    overdrive_irq       , irq_mask */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 0 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 7}, /* 1 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 6}, /* 2 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 3 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 5}, /* 4 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 5 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 6 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 4}, /* 7 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 8 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 9 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 3}, /* 10 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 2}, /* 11 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 12 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, 1}, /* 13 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE},   /* 14 */
-       {EXTERNAL_IRQ_NOT_ASSIGNED, EXTERNAL_IRQ_NOT_IN_USE}    /* 15 */
-};
-
-static void set_od_data(int overdrive_irq, int irq)
-{
-       if (irq >= NUM_EXTERNAL_IRQS || irq < 0)
-               return;
-       od_data_table[irq].overdrive_irq = overdrive_irq << 2;
-}
-
-static void enable_od_irq(unsigned int irq);
-void disable_od_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_od_irq disable_od_irq
-
-static void mask_and_ack_od(unsigned int);
-static void end_od_irq(unsigned int irq);
-
-static unsigned int startup_od_irq(unsigned int irq)
-{
-       enable_od_irq(irq);
-       return 0;               /* never anything pending */
-}
-
-static struct hw_interrupt_type od_irq_type = {
-       .typename = "Overdrive-IRQ",
-       .startup = startup_od_irq,
-       .shutdown = shutdown_od_irq,
-       .enable = enable_od_irq,
-       .disable = disable_od_irq,
-       .ack = mask_and_ack_od,
-       .end = end_od_irq
-};
-
-static void disable_od_irq(unsigned int irq)
-{
-       unsigned val, flags;
-       int overdrive_irq;
-       unsigned mask;
-
-       /* Not a valid interrupt */
-       if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
-               return;
-
-        /* Is is necessary to use a cli here? Would a spinlock not be 
-         * mroe efficient?
-         */
-       local_irq_save(flags);
-       overdrive_irq = od_data_table[irq].overdrive_irq;
-       if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
-               mask = ~(0x7 << overdrive_irq);
-               val = ctrl_inl(OVERDRIVE_INT_CT);
-               val &= mask;
-               ctrl_outl(val, OVERDRIVE_INT_CT);
-       }
-       local_irq_restore(flags);
-}
-
-static void enable_od_irq(unsigned int irq)
-{
-       unsigned val, flags;
-       int overdrive_irq;
-       unsigned mask;
-
-       /* Not a valid interrupt */
-       if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
-               return;
-
-       /* Set priority in OD back to original value */
-       local_irq_save(flags);
-       /* This one is not in use currently */
-       overdrive_irq = od_data_table[irq].overdrive_irq;
-       if (overdrive_irq != EXTERNAL_IRQ_NOT_ASSIGNED) {
-               val = ctrl_inl(OVERDRIVE_INT_CT);
-               mask = ~(0x7 << overdrive_irq);
-               val &= mask;
-               mask = od_data_table[irq].irq_mask << overdrive_irq;
-               val |= mask;
-               ctrl_outl(val, OVERDRIVE_INT_CT);
-       }
-       local_irq_restore(flags);
-}
-
-
-
-/* this functions sets the desired irq handler to be an overdrive type */
-static void __init make_od_irq(unsigned int irq)
-{
-       disable_irq_nosync(irq);
-       irq_desc[irq].chip = &od_irq_type;
-       disable_od_irq(irq);
-}
-
-
-static void mask_and_ack_od(unsigned int irq)
-{
-       disable_od_irq(irq);
-}
-
-static void end_od_irq(unsigned int irq)
-{
-       enable_od_irq(irq);
-}
-
-void __init init_overdrive_irq(void)
-{
-       int i;
-
-       /* Disable all interrupts */
-       ctrl_outl(0, OVERDRIVE_INT_CT);
-
-       /* Update interrupt pin mode to use encoded interrupts */
-       i = ctrl_inw(INTC_ICR);
-       i &= ~INTC_ICR_IRLM;
-       ctrl_outw(i, INTC_ICR);
-
-       for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
-               if (od_data_table[i].irq_mask != EXTERNAL_IRQ_NOT_IN_USE) {
-                       make_od_irq(i);
-               } else if (i != 15) {   // Cannot use imask on level 15
-                       make_imask_irq(i);
-               }
-       }
-
-       /* Set up the interrupts */
-       set_od_data(OVERDRIVE_PCI_INTA, OVERDRIVE_PCI_IRQ1);
-       set_od_data(OVERDRIVE_PCI_INTB, OVERDRIVE_PCI_IRQ2);
-       set_od_data(OVERDRIVE_AUDIO_INT, OVERDRIVE_ESS_IRQ);
-}
diff --git a/arch/sh/boards/overdrive/led.c b/arch/sh/boards/overdrive/led.c
deleted file mode 100644 (file)
index 860d7f2..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * linux/arch/sh/overdrive/led.c
- *
- * Copyright (C) 1999 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 an Overdrive specific LED feature.
- */
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/overdrive/overdrive.h>
-
-static void mach_led(int position, int value)
-{
-       unsigned long flags;
-       unsigned long reg;
-
-       local_irq_save(flags);
-       
-       reg = readl(OVERDRIVE_CTRL);
-       if (value) {
-               reg |= (1<<3);
-       } else {
-               reg &= ~(1<<3);
-       }
-       writel(reg, OVERDRIVE_CTRL);
-
-       local_irq_restore(flags);
-}
-
-#ifdef CONFIG_HEARTBEAT
-
-#include <linux/sched.h>
-
-/* acts like an actual heart beat -- ie thump-thump-pause... */
-void heartbeat_od(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/overdrive/mach.c b/arch/sh/boards/overdrive/mach.c
deleted file mode 100644 (file)
index 2834a03..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * linux/arch/sh/overdrive/mach.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.
- *
- * Machine vector for the STMicroelectronics Overdrive
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/io_unknown.h>
-#include <asm/io_generic.h>
-#include <asm/overdrive/io.h>
-
-void heartbeat_od(void);
-void init_overdrive_irq(void);
-void galileo_pcibios_init(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_od __initmv = {
-       .mv_nr_irqs             = 48,
-
-       .mv_inb                 = od_inb,
-       .mv_inw                 = od_inw,
-       .mv_inl                 = od_inl,
-       .mv_outb                = od_outb,
-       .mv_outw                = od_outw,
-       .mv_outl                = od_outl,
-
-       .mv_inb_p               = od_inb_p,
-       .mv_inw_p               = od_inw_p,
-       .mv_inl_p               = od_inl_p,
-       .mv_outb_p              = od_outb_p,
-       .mv_outw_p              = od_outw_p,
-       .mv_outl_p              = od_outl_p,
-
-       .mv_insb                = od_insb,
-       .mv_insw                = od_insw,
-       .mv_insl                = od_insl,
-       .mv_outsb               = od_outsb,
-       .mv_outsw               = od_outsw,
-       .mv_outsl               = od_outsl,
-
-#ifdef CONFIG_PCI
-       .mv_init_irq            = init_overdrive_irq,
-#endif
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_od,
-#endif
-};
-
-ALIAS_MV(od)
diff --git a/arch/sh/boards/overdrive/pcidma.c b/arch/sh/boards/overdrive/pcidma.c
deleted file mode 100644 (file)
index 1c9bfed..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * Dynamic DMA mapping support.
- *
- * On the overdrive, we can only DMA from memory behind the PCI bus!
- * this means that all DMA'able memory must come from there. 
- * this restriction will not apply to later boards.
- */
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <asm/io.h>
-
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-                          dma_addr_t * dma_handle)
-{
-       void *ret;
-       int gfp = GFP_ATOMIC;
-
-        printk("BUG: pci_alloc_consistent() called - not yet supported\n");
-       /* We ALWAYS need DMA memory on the overdrive hardware,
-        * due to it's extreme weirdness
-        * Need to flush the cache here as well, since the memory
-        * can still be seen through the cache!
-        */
-       gfp |= GFP_DMA;
-       ret = (void *) __get_free_pages(gfp, get_order(size));
-
-       if (ret != NULL) {
-               memset(ret, 0, size);
-               *dma_handle = virt_to_bus(ret);
-       }
-       return ret;
-}
-
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-                        void *vaddr, dma_addr_t dma_handle)
-{
-       free_pages((unsigned long) vaddr, get_order(size));
-}
diff --git a/arch/sh/boards/overdrive/setup.c b/arch/sh/boards/overdrive/setup.c
deleted file mode 100644 (file)
index a3a7744..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * arch/sh/overdrive/setup.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.
- *
- * STMicroelectronics Overdrive Support.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-
-#include <asm/overdrive/overdrive.h>
-#include <asm/overdrive/fpga.h>
-
-const char *get_system_type(void)
-{
-       return "SH7750 Overdrive";
-}
-
-/*
- * Initialize the board
- */
-int __init platform_setup(void)
-{
-#ifdef CONFIG_PCI
-       init_overdrive_fpga();
-       galileo_init();
-#endif
-
-        /* Enable RS232 receive buffers */
-       writel(0x1e, OVERDRIVE_CTRL);
-}
index 7fccbf2e4a1db776906a1c41eadd39cafbb8bd83..14bdd531f11627be815e69df5206bff15c3deeaf 100644 (file)
@@ -1,10 +1,6 @@
 #
 # Makefile for the EDOSK7705 specific parts of the kernel
 #
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
 
 obj-y   := setup.o io.o
 
index ba143fa4afaafd99f23ae0120c992778b45c00c3..ec5be0107719ecea1d340d4e68e78ecc6c832c64 100644 (file)
@@ -8,19 +8,21 @@
  * Modified for edosk7705 development
  * board by S. Dunn, 2003.
  */
-
 #include <linux/init.h>
 #include <asm/machvec.h>
-#include <asm/machvec_init.h>
 #include <asm/edosk7705/io.h>
 
-static void init_edosk7705(void);
+static void __init sh_edosk7705_init_irq(void)
+{
+       /* This is the Ethernet interrupt */
+       make_imask_irq(0x09);
+}
 
 /*
  * The Machine Vector
  */
-
 struct sh_machine_vector mv_edosk7705 __initmv = {
+       .mv_name                = "EDOSK7705",
        .mv_nr_irqs             = 80,
 
        .mv_inb                 = sh_edosk7705_inb,
@@ -37,23 +39,6 @@ struct sh_machine_vector mv_edosk7705 __initmv = {
        .mv_outsl               = sh_edosk7705_outsl,
 
        .mv_isa_port2addr       = sh_edosk7705_isa_port2addr,
-       .mv_init_irq            = init_edosk7705,
+       .mv_init_irq            = sh_edosk7705_init_irq,
 };
 ALIAS_MV(edosk7705)
-
-static void __init init_edosk7705(void)
-{
-       /* This is the Ethernet interrupt */
-       make_imask_irq(0x09);
-}
-
-const char *get_system_type(void)
-{
-       return "EDOSK7705";
-}
-
-void __init platform_setup(void)
-{
-       /* Nothing .. */
-}
-
diff --git a/arch/sh/boards/renesas/hs7751rvoip/Kconfig b/arch/sh/boards/renesas/hs7751rvoip/Kconfig
new file mode 100644 (file)
index 0000000..1743be4
--- /dev/null
@@ -0,0 +1,12 @@
+if SH_HS7751RVOIP
+
+menu "HS7751RVoIP options"
+
+config HS7751RVOIP_CODEC
+       bool "Support VoIP Codec section"
+       help
+         Selecting this option will support CODEC section.
+
+endmenu
+
+endif
index e8b4109ace117c662068b1fa78d43f639cc85f1f..e626377c55eecc1e591fda6b2ee25523f3ac4139 100644 (file)
@@ -1,12 +1,8 @@
 #
 # Makefile for the HS7751RVoIP specific parts of the kernel
 #
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
 
-obj-y   := mach.o setup.o io.o irq.o led.o
+obj-y   := setup.o io.o irq.o
 
 obj-$(CONFIG_PCI) += pci.o
 
index 3a1abfa2fefb99917b4df26e990b44acab14b899..9ea1136b219b2ca9fa78cbbeda1d2127aa237fb3 100644 (file)
  * placeholder code from io_hs7751rvoip.c left in with the
  * expectation of later SuperIO and PCMCIA access.
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/hs7751rvoip/hs7751rvoip.h>
 #include <asm/addrspace.h>
 
-#include <linux/module.h>
-#include <linux/pci.h>
-#include "../../../drivers/pci/pci-sh7751.h"
-
-extern void *area5_io8_base;   /* Area 5 8bit I/O Base address */
 extern void *area6_io8_base;   /* Area 6 8bit I/O Base address */
 extern void *area5_io16_base;  /* Area 5 16bit I/O Base address */
-extern void *area6_io16_base;  /* Area 6 16bit I/O Base address */
 
 /*
  * The 7751R HS7751RVoIP uses the built-in PCI controller (PCIC)
@@ -33,25 +28,8 @@ extern void *area6_io16_base;        /* Area 6 16bit I/O Base address */
  * like the other Solution Engine boards.
  */
 
-#define PCIIOBR                (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA    SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA   SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-#if defined(CONFIG_HS7751RVOIP_CODEC)
 #define CODEC_IO_BASE  0x1000
-#endif
-
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
+#define CODEC_IOMAP(a) ((unsigned long)area6_io8_base + ((a) - CODEC_IO_BASE))
 
 static inline unsigned long port2adr(unsigned int port)
 {
@@ -59,9 +37,10 @@ static inline unsigned long port2adr(unsigned int port)
                if (port == 0x3f6)
                        return ((unsigned long)area5_io16_base + 0x0c);
                else
-                       return ((unsigned long)area5_io16_base + 0x800 + ((port-0x1f0) << 1));
+                       return ((unsigned long)area5_io16_base + 0x800 +
+                               ((port-0x1f0) << 1));
        else
-               maybebadio(port2adr, (unsigned long)port);
+               maybebadio((unsigned long)port);
        return port;
 }
 
@@ -78,25 +57,10 @@ static inline int shifted_port(unsigned long port)
 }
 
 #if defined(CONFIG_HS7751RVOIP_CODEC)
-static inline int
-codec_port(unsigned long port)
-{
-       if (CODEC_IO_BASE <= port && port < (CODEC_IO_BASE+0x20))
-               return 1;
-       else
-               return 0;
-}
-#endif
-
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
-  ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
+#define codec_port(port)       \
+       ((CODEC_IO_BASE <= (port)) && ((port) < (CODEC_IO_BASE + 0x20)))
 #else
-#define CHECK_SH7751_PCIIO(port) (0)
+#define codec_port(port)       (0)
 #endif
 
 /*
@@ -109,15 +73,13 @@ codec_port(unsigned long port)
 unsigned char hs7751rvoip_inb(unsigned long port)
 {
        if (PXSEG(port))
-               return *(volatile unsigned char *)port;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               return ctrl_inb(port);
        else if (codec_port(port))
-               return *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               return *(volatile unsigned char *)PCI_IOMAP(port);
+               return ctrl_inb(CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return ctrl_inb(pci_ioaddr(port));
        else
-               return (*(volatile unsigned short *)port2adr(port) & 0xff);
+               return ctrl_inw(port2adr(port)) & 0xff;
 }
 
 unsigned char hs7751rvoip_inb_p(unsigned long port)
@@ -125,38 +87,36 @@ unsigned char hs7751rvoip_inb_p(unsigned long port)
        unsigned char v;
 
         if (PXSEG(port))
-                v = *(volatile unsigned char *)port;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               v = ctrl_inb(port);
        else if (codec_port(port))
-               v = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-                v = *(volatile unsigned char *)PCI_IOMAP(port);
+               v = ctrl_inb(CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               v = ctrl_inb(pci_ioaddr(port));
        else
-               v = (*(volatile unsigned short *)port2adr(port) & 0xff);
-       delay();
+               v = ctrl_inw(port2adr(port)) & 0xff;
+       ctrl_delay();
        return v;
 }
 
 unsigned short hs7751rvoip_inw(unsigned long port)
 {
         if (PXSEG(port))
-                return *(volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-                return *(volatile unsigned short *)PCI_IOMAP(port);
+               return ctrl_inw(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return ctrl_inw(pci_ioaddr(port));
        else
-               maybebadio(inw, port);
+               maybebadio(port);
        return 0;
 }
 
 unsigned int hs7751rvoip_inl(unsigned long port)
 {
         if (PXSEG(port))
-                return *(volatile unsigned long *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-                return *(volatile unsigned long *)PCI_IOMAP(port);
+               return ctrl_inl(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return ctrl_inl(pci_ioaddr(port));
        else
-               maybebadio(inl, port);
+               maybebadio(port);
        return 0;
 }
 
@@ -164,146 +124,160 @@ void hs7751rvoip_outb(unsigned char value, unsigned long port)
 {
 
         if (PXSEG(port))
-                *(volatile unsigned char *)port = value;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               ctrl_outb(value, port);
        else if (codec_port(port))
-               *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value;
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(unsigned char *)PCI_IOMAP(port) = value;
+               ctrl_outb(value, CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outb(value, pci_ioaddr(port));
        else
-               *(volatile unsigned short *)port2adr(port) = value;
+               ctrl_outb(value, port2adr(port));
 }
 
 void hs7751rvoip_outb_p(unsigned char value, unsigned long port)
 {
         if (PXSEG(port))
-                *(volatile unsigned char *)port = value;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               ctrl_outb(value, port);
        else if (codec_port(port))
-               *(volatile unsigned cjar *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = value;
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(unsigned char *)PCI_IOMAP(port) = value;
+               ctrl_outb(value, CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outb(value, pci_ioaddr(port));
        else
-               *(volatile unsigned short *)port2adr(port) = value;
-       delay();
+               ctrl_outw(value, port2adr(port));
+
+       ctrl_delay();
 }
 
 void hs7751rvoip_outw(unsigned short value, unsigned long port)
 {
         if (PXSEG(port))
-                *(volatile unsigned short *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(unsigned short *)PCI_IOMAP(port) = value;
+               ctrl_outw(value, port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outw(value, pci_ioaddr(port));
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
 void hs7751rvoip_outl(unsigned int value, unsigned long port)
 {
         if (PXSEG(port))
-                *(volatile unsigned long *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *((unsigned long *)PCI_IOMAP(port)) = value;
+               ctrl_outl(value, port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               ctrl_outl(value, pci_ioaddr(port));
        else
-               maybebadio(outl, port);
+               maybebadio(port);
 }
 
 void hs7751rvoip_insb(unsigned long port, void *addr, unsigned long count)
 {
+       u8 *buf = addr;
+
        if (PXSEG(port))
-               while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)port;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               while (count--)
+                       *buf++ = ctrl_inb(port);
        else if (codec_port(port))
-               while (count--) *((unsigned char *) addr)++ = *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE));
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u8 *bp = (__u8 *)PCI_IOMAP(port);
+               while (count--)
+                       *buf++ = ctrl_inb(CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
 
-               while (count--) *((volatile unsigned char *) addr)++ = *bp;
+               while (count--)
+                       *buf++ = *bp;
        } else {
-               volatile __u16 *p = (volatile unsigned short *)port2adr(port);
+               volatile u16 *p = (volatile u16 *)port2adr(port);
 
-               while (count--) *((unsigned char *) addr)++ = *p & 0xff;
+               while (count--)
+                       *buf++ = *p & 0xff;
        }
 }
 
 void hs7751rvoip_insw(unsigned long port, void *addr, unsigned long count)
 {
-       volatile __u16 *p;
+       volatile u16 *p;
+       u16 *buf = addr;
 
        if (PXSEG(port))
-               p = (volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               p = (volatile unsigned short *)PCI_IOMAP(port);
+               p = (volatile u16 *)port;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               p = (volatile u16 *)pci_ioaddr(port);
        else
-               p = (volatile unsigned short *)port2adr(port);
-       while (count--) *((__u16 *) addr)++ = *p;
+               p = (volatile u16 *)port2adr(port);
+       while (count--)
+               *buf++ = *p;
 }
 
 void hs7751rvoip_insl(unsigned long port, void *addr, unsigned long count)
 {
-       if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
 
-               while (count--) *((__u32 *) addr)++ = *p;
+       if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+               u32 *buf = addr;
+
+               while (count--)
+                       *buf++ = *p;
        } else
-               maybebadio(insl, port);
+               maybebadio(port);
 }
 
 void hs7751rvoip_outsb(unsigned long port, const void *addr, unsigned long count)
 {
+       const u8 *buf = addr;
+
        if (PXSEG(port))
-               while (count--) *(volatile unsigned char *)port = *((unsigned char *) addr)++;
-#if defined(CONFIG_HS7751RVOIP_CODEC)
+               while (count--)
+                       ctrl_outb(*buf++, port);
        else if (codec_port(port))
-               while (count--) *(volatile unsigned char *)((unsigned long)area6_io8_base+(port-CODEC_IO_BASE)) = *((unsigned char *) addr)++;
-#endif
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u8 *bp = (__u8 *)PCI_IOMAP(port);
+               while (count--)
+                       ctrl_outb(*buf++, CODEC_IOMAP(port));
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
 
-               while (count--) *bp = *((volatile unsigned char *) addr)++;
+               while (count--)
+                       *bp = *buf++;
        } else {
-               volatile __u16 *p = (volatile unsigned short *)port2adr(port);
+               volatile u16 *p = (volatile u16 *)port2adr(port);
 
-               while (count--) *p = *((unsigned char *) addr)++;
+               while (count--)
+                       *p = *buf++;
        }
 }
 
 void hs7751rvoip_outsw(unsigned long port, const void *addr, unsigned long count)
 {
-       volatile __u16 *p;
+       volatile u16 *p;
+       const u16 *buf = addr;
 
        if (PXSEG(port))
-               p = (volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               p = (volatile unsigned short *)PCI_IOMAP(port);
+               p = (volatile u16 *)port;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               p = (volatile u16 *)pci_ioaddr(port);
        else
-               p = (volatile unsigned short *)port2adr(port);
-       while (count--) *p = *((__u16 *) addr)++;
+               p = (volatile u16 *)port2adr(port);
+
+       while (count--)
+               *p = *buf++;
 }
 
 void hs7751rvoip_outsl(unsigned long port, const void *addr, unsigned long count)
 {
-       if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
+       const u32 *buf = addr;
 
-               while (count--) *p = *((__u32 *) addr)++;
+       if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+               while (count--)
+                       *p = *buf++;
        } else
-               maybebadio(outsl, port);
+               maybebadio(port);
 }
 
-void *hs7751rvoip_ioremap(unsigned long offset, unsigned long size)
+void __iomem *hs7751rvoip_ioport_map(unsigned long port, unsigned int size)
 {
-       if (offset >= 0xfd000000)
-               return (void *)offset;
-       else
-               return (void *)P2SEGADDR(offset);
-}
-EXPORT_SYMBOL(hs7751rvoip_ioremap);
+        if (PXSEG(port))
+                return (void __iomem *)port;
+       else if (unlikely(codec_port(port) && (size == 1)))
+               return (void __iomem *)CODEC_IOMAP(port);
+        else if (is_pci_ioaddr(port))
+                return (void __iomem *)pci_ioaddr(port);
 
-unsigned long hs7751rvoip_isa_port2addr(unsigned long offset)
-{
-       return port2adr(offset);
+        return (void __iomem *)port2adr(port);
 }
index 705b7ddcb0d28a4f17dd9197fbd9124238063d2d..c617b188258a0e4a27bbb731f4ec99e48c0cdad3 100644 (file)
@@ -35,30 +35,24 @@ static unsigned int startup_hs7751rvoip_irq(unsigned int irq)
 
 static void disable_hs7751rvoip_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short val;
        unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
 
        /* Set the priority in IPR to 0 */
-       local_irq_save(flags);
        val = ctrl_inw(IRLCNTR3);
        val &= mask;
        ctrl_outw(val, IRLCNTR3);
-       local_irq_restore(flags);
 }
 
 static void enable_hs7751rvoip_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short val;
        unsigned short value = (0x0001 << mask_pos[irq]);
 
        /* Set priority in IPR back to original value */
-       local_irq_save(flags);
        val = ctrl_inw(IRLCNTR3);
        val |= value;
        ctrl_outw(val, IRLCNTR3);
-       local_irq_restore(flags);
 }
 
 static void ack_hs7751rvoip_irq(unsigned int irq)
diff --git a/arch/sh/boards/renesas/hs7751rvoip/led.c b/arch/sh/boards/renesas/hs7751rvoip/led.c
deleted file mode 100644 (file)
index b6608ff..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * linux/arch/sh/kernel/setup_hs7751rvoip.c
- *
- * Copyright (C) 2000  Kazumoto Kojima
- *
- * Renesas Technology Sales HS7751RVoIP Support.
- *
- * Modified for HS7751RVoIP by
- * Atom Create Engineering Co., Ltd. 2002.
- * Lineo uSolutions, Inc. 2003.
- */
-
-#include <asm/io.h>
-#include <asm/hs7751rvoip/hs7751rvoip.h>
-
-extern unsigned int debug_counter;
-
-void debug_led_disp(void)
-{
-       unsigned short value;
-
-       value = (unsigned char)debug_counter++;
-       ctrl_outb((0xf0|value), PA_OUTPORTR);
-       if (value == 0x0f)
-               debug_counter = 0;
-}
diff --git a/arch/sh/boards/renesas/hs7751rvoip/mach.c b/arch/sh/boards/renesas/hs7751rvoip/mach.c
deleted file mode 100644 (file)
index caf967f..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_hs7751rvoip.c
- *
- * Minor tweak of mach_se.c file to reference hs7751rvoip-specific items.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the Renesas Technology sales HS7751RVoIP
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/irq.h>
-#include <asm/hs7751rvoip/io.h>
-
-extern void init_hs7751rvoip_IRQ(void);
-extern void *hs7751rvoip_ioremap(unsigned long, unsigned long);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_hs7751rvoip __initmv = {
-       .mv_nr_irqs             = 72,
-
-       .mv_inb                 = hs7751rvoip_inb,
-       .mv_inw                 = hs7751rvoip_inw,
-       .mv_inl                 = hs7751rvoip_inl,
-       .mv_outb                = hs7751rvoip_outb,
-       .mv_outw                = hs7751rvoip_outw,
-       .mv_outl                = hs7751rvoip_outl,
-
-       .mv_inb_p               = hs7751rvoip_inb_p,
-       .mv_inw_p               = hs7751rvoip_inw,
-       .mv_inl_p               = hs7751rvoip_inl,
-       .mv_outb_p              = hs7751rvoip_outb_p,
-       .mv_outw_p              = hs7751rvoip_outw,
-       .mv_outl_p              = hs7751rvoip_outl,
-
-       .mv_insb                = hs7751rvoip_insb,
-       .mv_insw                = hs7751rvoip_insw,
-       .mv_insl                = hs7751rvoip_insl,
-       .mv_outsb               = hs7751rvoip_outsb,
-       .mv_outsw               = hs7751rvoip_outsw,
-       .mv_outsl               = hs7751rvoip_outsl,
-
-       .mv_ioremap             = hs7751rvoip_ioremap,
-       .mv_isa_port2addr       = hs7751rvoip_isa_port2addr,
-       .mv_init_irq            = init_hs7751rvoip_IRQ,
-};
-ALIAS_MV(hs7751rvoip)
index 29fb5ff70fb54fc9f7b19f2ac3612820c7deb925..0414c15c3458da63969f97c7cf3ddb923646bbdb 100644 (file)
@@ -1,44 +1,38 @@
 /*
- * linux/arch/sh/kernel/setup_hs7751rvoip.c
+ * Renesas Technology Sales HS7751RVoIP Support.
  *
  * Copyright (C) 2000  Kazumoto Kojima
  *
- * Renesas Technology Sales HS7751RVoIP Support.
- *
  * Modified for HS7751RVoIP by
  * Atom Create Engineering Co., Ltd. 2002.
  * Lineo uSolutions, Inc. 2003.
  */
-
 #include <linux/init.h>
 #include <linux/irq.h>
-
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/pm.h>
 #include <asm/io.h>
 #include <asm/hs7751rvoip/hs7751rvoip.h>
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/irq.h>
 
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-
-/* defined in mm/ioremap.c */
-extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
-
-unsigned int debug_counter;
-
-const char *get_system_type(void)
+static void __init hs7751rvoip_init_irq(void)
 {
-       return "HS7751RVoIP";
+#if defined(CONFIG_HS7751RVOIP_CODEC)
+       make_ipr_irq(DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+       make_ipr_irq(DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+#endif
+
+       init_hs7751rvoip_IRQ();
 }
 
-/*
- * Initialize the board
- */
-void __init platform_setup(void)
+static void hs7751rvoip_power_off(void)
 {
-       printk(KERN_INFO "Renesas Technology Sales HS7751RVoIP-2 support.\n");
-       ctrl_outb(0xf0, PA_OUTPORTR);
-       debug_counter = 0;
+       ctrl_outw(ctrl_inw(PA_OUTPORTR) & 0xffdf, PA_OUTPORTR);
 }
 
 void *area5_io8_base;
@@ -46,16 +40,15 @@ void *area6_io8_base;
 void *area5_io16_base;
 void *area6_io16_base;
 
-int __init cf_init(void)
+static int __init hs7751rvoip_cf_init(void)
 {
        pgprot_t prot;
-       unsigned long paddrbase, psize;
+       unsigned long paddrbase;
 
        /* open I/O area window */
        paddrbase = virt_to_phys((void *)(PA_AREA5_IO+0x00000800));
-       psize = PAGE_SIZE;
        prot = PAGE_KERNEL_PCC(1, _PAGE_PCC_COM16);
-       area5_io16_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+       area5_io16_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
        if (!area5_io16_base) {
                printk("allocate_cf_area : can't open CF I/O window!\n");
                return -ENOMEM;
@@ -64,19 +57,18 @@ int __init cf_init(void)
        /* XXX : do we need attribute and common-memory area also? */
 
        paddrbase = virt_to_phys((void *)PA_AREA6_IO);
-       psize = PAGE_SIZE;
 #if defined(CONFIG_HS7751RVOIP_CODEC)
        prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_COM8);
 #else
        prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO8);
 #endif
-       area6_io8_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+       area6_io8_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
        if (!area6_io8_base) {
                printk("allocate_cf_area : can't open CODEC I/O 8bit window!\n");
                return -ENOMEM;
        }
        prot = PAGE_KERNEL_PCC(0, _PAGE_PCC_IO16);
-       area6_io16_base = p3_ioremap(paddrbase, psize, prot.pgprot);
+       area6_io16_base = p3_ioremap(paddrbase, PAGE_SIZE, prot.pgprot);
        if (!area6_io16_base) {
                printk("allocate_cf_area : can't open CODEC I/O 16bit window!\n");
                return -ENOMEM;
@@ -85,4 +77,46 @@ int __init cf_init(void)
        return 0;
 }
 
-__initcall (cf_init);
+/*
+ * Initialize the board
+ */
+static void __init hs7751rvoip_setup(char **cmdline_p)
+{
+       device_initcall(hs7751rvoip_cf_init);
+
+       ctrl_outb(0xf0, PA_OUTPORTR);
+       pm_power_off = hs7751rvoip_power_off;
+
+       printk(KERN_INFO "Renesas Technology Sales HS7751RVoIP-2 support.\n");
+}
+
+struct sh_machine_vector mv_hs7751rvoip __initmv = {
+       .mv_name                = "HS7751RVoIP",
+       .mv_setup               = hs7751rvoip_setup,
+       .mv_nr_irqs             = 72,
+
+       .mv_inb                 = hs7751rvoip_inb,
+       .mv_inw                 = hs7751rvoip_inw,
+       .mv_inl                 = hs7751rvoip_inl,
+       .mv_outb                = hs7751rvoip_outb,
+       .mv_outw                = hs7751rvoip_outw,
+       .mv_outl                = hs7751rvoip_outl,
+
+       .mv_inb_p               = hs7751rvoip_inb_p,
+       .mv_inw_p               = hs7751rvoip_inw,
+       .mv_inl_p               = hs7751rvoip_inl,
+       .mv_outb_p              = hs7751rvoip_outb_p,
+       .mv_outw_p              = hs7751rvoip_outw,
+       .mv_outl_p              = hs7751rvoip_outl,
+
+       .mv_insb                = hs7751rvoip_insb,
+       .mv_insw                = hs7751rvoip_insw,
+       .mv_insl                = hs7751rvoip_insl,
+       .mv_outsb               = hs7751rvoip_outsb,
+       .mv_outsw               = hs7751rvoip_outsw,
+       .mv_outsl               = hs7751rvoip_outsl,
+
+       .mv_init_irq            = hs7751rvoip_init_irq,
+       .mv_ioport_map          = hs7751rvoip_ioport_map,
+};
+ALIAS_MV(hs7751rvoip)
diff --git a/arch/sh/boards/renesas/r7780rp/Kconfig b/arch/sh/boards/renesas/r7780rp/Kconfig
new file mode 100644 (file)
index 0000000..c26d981
--- /dev/null
@@ -0,0 +1,14 @@
+if SH_R7780RP
+
+menu "R7780RP options"
+
+config SH_R7780MP
+       bool "R7780MP board support"
+       default y
+       help
+         Selecting this option will enable support for the mass-production
+         version of the R7780RP. If in doubt, say Y.
+
+endmenu
+
+endif
diff --git a/arch/sh/boards/renesas/r7780rp/Makefile b/arch/sh/boards/renesas/r7780rp/Makefile
new file mode 100644 (file)
index 0000000..f1776d0
--- /dev/null
@@ -0,0 +1,6 @@
+#
+# Makefile for the R7780RP-1 specific parts of the kernel
+#
+
+obj-y   := setup.o io.o irq.o
+obj-$(CONFIG_HEARTBEAT)        += led.o
diff --git a/arch/sh/boards/renesas/r7780rp/io.c b/arch/sh/boards/renesas/r7780rp/io.c
new file mode 100644 (file)
index 0000000..db92d6e
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
+ * Based largely on io_se.c.
+ *
+ * I/O routine for Renesas Solutions Highlander R7780RP-1
+ *
+ * Initial version only to support LAN access; some
+ * placeholder code from io_r7780rp.c left in with the
+ * expectation of later SuperIO and PCMCIA access.
+ */
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/r7780rp/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)
+{
+       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 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)))
+#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.
+ */
+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))
+               return ctrl_inb(pci_ioaddr(port));
+
+       return ctrl_inw(port2adr(port)) & 0xff;
+}
+
+u8 r7780rp_inb_p(unsigned long port)
+{
+       u8 v;
+
+       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))
+               v = ctrl_inb(pci_ioaddr(port));
+       else
+               v = ctrl_inw(port2adr(port)) & 0xff;
+
+       ctrl_delay();
+
+       return v;
+}
+
+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))
+               return ctrl_inw(pci_ioaddr(port));
+       else
+               maybebadio(port);
+
+       return 0;
+}
+
+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))
+               return ctrl_inl(pci_ioaddr(port));
+       else
+               maybebadio(port);
+
+       return 0;
+}
+
+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))
+               ctrl_outb(value, pci_ioaddr(port));
+       else
+               ctrl_outw(value, port2adr(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))
+               ctrl_outb(value, pci_ioaddr(port));
+       else
+               ctrl_outw(value, port2adr(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))
+               ctrl_outw(value, pci_ioaddr(port));
+       else
+               maybebadio(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))
+               ctrl_outl(value, pci_ioaddr(port));
+       else
+               maybebadio(port);
+}
+
+void r7780rp_insb(unsigned long port, void *dst, unsigned long count)
+{
+       volatile u16 *p;
+       u8 *buf = dst;
+
+       if (CHECK_AX88796L_PORT(port)) {
+               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)) {
+               volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
+
+               while (count--)
+                       *buf++ = *bp;
+       } else {
+               p = (volatile u16 *)port2adr(port);
+               while (count--)
+                       *buf++ = *p & 0xff;
+       }
+}
+
+void r7780rp_insw(unsigned long port, void *dst, unsigned long count)
+{
+       volatile u16 *p;
+       u16 *buf = dst;
+
+       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))
+               p = (volatile u16 *)pci_ioaddr(port);
+       else
+               p = (volatile u16 *)port2adr(port);
+
+       while (count--)
+               *buf++ = *p;
+}
+
+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)) {
+               volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+               while (count--)
+                       *buf++ = *p;
+       } else
+               maybebadio(port);
+}
+
+void r7780rp_outsb(unsigned long port, const void *src, unsigned long count)
+{
+       volatile u16 *p;
+       const u8 *buf = src;
+
+       if (CHECK_AX88796L_PORT(port)) {
+               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)) {
+               volatile u8 *bp = (volatile u8 *)pci_ioaddr(port);
+
+               while (count--)
+                       *bp = *buf++;
+       } else {
+               p = (volatile u16 *)port2adr(port);
+               while (count--)
+                       *p = *buf++;
+       }
+}
+
+void r7780rp_outsw(unsigned long port, const void *src, unsigned long count)
+{
+       volatile u16 *p;
+       const u16 *buf = src;
+
+       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))
+               p = (volatile u16 *)pci_ioaddr(port);
+       else
+               p = (volatile u16 *)port2adr(port);
+
+       while (count--)
+               *p = *buf++;
+}
+
+void r7780rp_outsl(unsigned long port, const void *src, unsigned long count)
+{
+       const u32 *buf = src;
+
+       if (CHECK_AX88796L_PORT(port))
+               maybebadio(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port)) {
+               volatile u32 *p = (volatile u32 *)pci_ioaddr(port);
+
+               while (count--)
+                       *p = *buf++;
+       } else
+               maybebadio(port);
+}
+
+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))
+               return (void __iomem *)pci_ioaddr(port);
+
+       return (void __iomem *)port2adr(port);
+}
diff --git a/arch/sh/boards/renesas/r7780rp/irq.c b/arch/sh/boards/renesas/r7780rp/irq.c
new file mode 100644 (file)
index 0000000..61d5e5d
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * linux/arch/sh/boards/renesas/r7780rp/irq.c
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Renesas Solutions Highlander R7780RP-1 Support.
+ *
+ * Modified for R7780RP-1 by
+ * Atom Create Engineering Co., Ltd. 2002.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/r7780rp/r7780rp.h>
+
+#ifdef CONFIG_SH_R7780MP
+static int mask_pos[] = {12, 11, 9, 14, 15, 8, 13, 6, 5, 4, 3, 2, 0, 0, 1, 0};
+#else
+static int mask_pos[] = {15, 14, 13, 12, 11, 10, 9, 8, 7, 5, 6, 4, 0, 1, 2, 0};
+#endif
+
+static void enable_r7780rp_irq(unsigned int irq);
+static void disable_r7780rp_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_r7780rp_irq disable_r7780rp_irq
+
+static void ack_r7780rp_irq(unsigned int irq);
+static void end_r7780rp_irq(unsigned int irq);
+
+static unsigned int startup_r7780rp_irq(unsigned int irq)
+{
+       enable_r7780rp_irq(irq);
+       return 0; /* never anything pending */
+}
+
+static void disable_r7780rp_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_r7780rp_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);
+}
+
+static void ack_r7780rp_irq(unsigned int irq)
+{
+       disable_r7780rp_irq(irq);
+}
+
+static void end_r7780rp_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+               enable_r7780rp_irq(irq);
+}
+
+static struct hw_interrupt_type r7780rp_irq_type = {
+       .typename = "R7780RP-IRQ",
+       .startup = startup_r7780rp_irq,
+       .shutdown = shutdown_r7780rp_irq,
+       .enable = enable_r7780rp_irq,
+       .disable = disable_r7780rp_irq,
+       .ack = ack_r7780rp_irq,
+       .end = end_r7780rp_irq,
+};
+
+static void make_r7780rp_irq(unsigned int irq)
+{
+       disable_irq_nosync(irq);
+       irq_desc[irq].handler = &r7780rp_irq_type;
+       disable_r7780rp_irq(irq);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_r7780rp_IRQ(void)
+{
+       int i;
+
+       /* IRL0=PCI Slot #A
+        * IRL1=PCI Slot #B
+        * IRL2=PCI Slot #C
+        * IRL3=PCI Slot #D
+        * IRL4=CF Card
+        * IRL5=CF Card Insert
+        * IRL6=M66596
+        * IRL7=SD Card
+        * IRL8=Touch Panel
+        * IRL9=SCI
+        * IRL10=Serial
+        * IRL11=Extention #A
+        * IRL11=Extention #B
+        * IRL12=Debug LAN
+        * IRL13=Push Switch
+        * IRL14=ZiggBee IO
+        */
+
+       for (i=0; i<15; i++)
+               make_r7780rp_irq(i);
+}
diff --git a/arch/sh/boards/renesas/r7780rp/led.c b/arch/sh/boards/renesas/r7780rp/led.c
new file mode 100644 (file)
index 0000000..9f02766
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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/config.h>
+#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--;
+}
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
new file mode 100644 (file)
index 0000000..b941aa0
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * arch/sh/boards/renesas/r7780rp/setup.c
+ *
+ * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2005, 2006 Paul Mundt
+ *
+ * Renesas Solutions Highlander R7780RP-1 Support.
+ *
+ * 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/platform_device.h>
+#include <asm/machvec.h>
+#include <asm/r7780rp/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[] = {
+       [0] = {
+               .start  = 0xa4800000,
+               .end    = 0xa4ffffff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 6,            /* irq number */
+               .end    = 6,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device m66596_usb_host_device = {
+       .name           = "m66596-hcd",
+       .id             = 0,
+       .dev = {
+               .dma_mask               = NULL,         /* don't use dma */
+               .coherent_dma_mask      = 0xffffffff,
+       },
+       .num_resources  = ARRAY_SIZE(m66596_usb_host_resources),
+       .resource       = m66596_usb_host_resources,
+};
+
+static struct platform_device *r7780rp_devices[] __initdata = {
+       &m66596_usb_host_device,
+};
+
+static int __init r7780rp_devices_setup(void)
+{
+       return platform_add_devices(r7780rp_devices,
+                                   ARRAY_SIZE(r7780rp_devices));
+}
+
+/*
+ * Platform specific clocks
+ */
+static void ivdr_clk_enable(struct clk *clk)
+{
+       ctrl_outw(ctrl_inw(PA_IVDRCTL) | (1 << 8), PA_IVDRCTL);
+}
+
+static void ivdr_clk_disable(struct clk *clk)
+{
+       ctrl_outw(ctrl_inw(PA_IVDRCTL) & ~(1 << 8), PA_IVDRCTL);
+}
+
+static struct clk_ops ivdr_clk_ops = {
+       .enable         = ivdr_clk_enable,
+       .disable        = ivdr_clk_disable,
+};
+
+static struct clk ivdr_clk = {
+       .name           = "ivdr_clk",
+       .ops            = &ivdr_clk_ops,
+};
+
+static struct clk *r7780rp_clocks[] = {
+       &ivdr_clk,
+};
+
+static void r7780rp_power_off(void)
+{
+#ifdef CONFIG_SH_R7780MP
+       ctrl_outw(0x0001, PA_POFF);
+#endif
+}
+
+/*
+ * Initialize the board
+ */
+static void __init r7780rp_setup(char **cmdline_p)
+{
+       u16 ver = ctrl_inw(PA_VERREG);
+       int i;
+
+       device_initcall(r7780rp_devices_setup);
+
+       printk(KERN_INFO "Renesas Solutions Highlander R7780RP-1 support.\n");
+
+       printk(KERN_INFO "Board version: %d (revision %d), "
+                        "FPGA version: %d (revision %d)\n",
+                        (ver >> 12) & 0xf, (ver >> 8) & 0xf,
+                        (ver >>  4) & 0xf, ver & 0xf);
+
+       /*
+        * Enable the important clocks right away..
+        */
+       for (i = 0; i < ARRAY_SIZE(r7780rp_clocks); i++) {
+               struct clk *clk = r7780rp_clocks[i];
+
+               clk_register(clk);
+               clk_enable(clk);
+       }
+
+       ctrl_outw(0x0000, PA_OBLED);    /* Clear LED. */
+#ifndef CONFIG_SH_R7780MP
+       ctrl_outw(0x0001, PA_SDPOW);    /* SD Power ON */
+#endif
+       ctrl_outw(ctrl_inw(PA_IVDRCTL) | 0x0100, PA_IVDRCTL);   /* Si13112 */
+
+       pm_power_off = r7780rp_power_off;
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_r7780rp __initmv = {
+       .mv_name                = "Highlander R7780RP-1",
+       .mv_setup               = r7780rp_setup,
+
+       .mv_nr_irqs             = 109,
+
+       .mv_inb                 = r7780rp_inb,
+       .mv_inw                 = r7780rp_inw,
+       .mv_inl                 = r7780rp_inl,
+       .mv_outb                = r7780rp_outb,
+       .mv_outw                = r7780rp_outw,
+       .mv_outl                = r7780rp_outl,
+
+       .mv_inb_p               = r7780rp_inb_p,
+       .mv_inw_p               = r7780rp_inw,
+       .mv_inl_p               = r7780rp_inl,
+       .mv_outb_p              = r7780rp_outb_p,
+       .mv_outw_p              = r7780rp_outw,
+       .mv_outl_p              = r7780rp_outl,
+
+       .mv_insb                = r7780rp_insb,
+       .mv_insw                = r7780rp_insw,
+       .mv_insl                = r7780rp_insl,
+       .mv_outsb               = r7780rp_outsb,
+       .mv_outsw               = r7780rp_outsw,
+       .mv_outsl               = r7780rp_outsl,
+
+       .mv_ioport_map          = r7780rp_ioport_map,
+       .mv_init_irq            = init_r7780rp_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = heartbeat_r7780rp,
+#endif
+};
+ALIAS_MV(r7780rp)
diff --git a/arch/sh/boards/renesas/rts7751r2d/Kconfig b/arch/sh/boards/renesas/rts7751r2d/Kconfig
new file mode 100644 (file)
index 0000000..7780d1f
--- /dev/null
@@ -0,0 +1,12 @@
+if SH_RTS7751R2D
+
+menu "RTS7751R2D options"
+
+config RTS7751R2D_REV11
+       bool "RTS7751R2D Rev. 1.1 board support"
+       help
+         Selecting this option will support version rev. 1.1.
+endmenu
+
+endif
+
index daa53334bdc31e23cc6506a9e863180fb0ab0cad..686fc9ea5989c01e1968c739eb8d1bd091c5bb5f 100644 (file)
@@ -1,10 +1,6 @@
 #
 # Makefile for the RTS7751R2D specific parts of the kernel
 #
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-obj-y   := mach.o setup.o io.o irq.o led.o
 
+obj-y   := setup.o io.o irq.o
+obj-$(CONFIG_HEARTBEAT) += led.o
index 123abbbc91e0c0b4dcec41827ed9a7c92814508f..135aa0b5e62dcc926d7df4f3c4996c70c1433c96 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/arch/sh/kernel/io_rts7751r2d.c
- *
  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
  * Based largely on io_se.c.
  *
  * 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 <asm/io.h>
+#include <linux/pci.h>
 #include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/io.h>
 #include <asm/addrspace.h>
 
-#include <linux/module.h>
-#include <linux/pci.h>
-#include "../../../drivers/pci/pci-sh7751.h"
-
 /*
  * The 7751R RTS7751R2D uses the built-in PCI controller (PCIC)
  * of the 7751R processor, and has a SuperIO accessible via the PCI.
  * like the other Solution Engine boards.
  */
 
-#define PCIIOBR                (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA    SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA   SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
 static inline unsigned long port2adr(unsigned int port)
 {
        if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
@@ -52,7 +30,7 @@ static inline unsigned long port2adr(unsigned int port)
                else
                        return (PA_AREA5_IO + 0x1000 + ((port-0x1f0) << 1));
        else
-               maybebadio(port2adr, (unsigned long)port);
+               maybebadio((unsigned long)port);
 
        return port;
 }
@@ -81,17 +59,6 @@ static inline int shifted_port(unsigned long port)
                return 1;
 }
 
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
-  ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(port) (0)
-#endif
-
 #if defined(CONFIG_NE2000) || defined(CONFIG_NE2000_MODULE)
 #define CHECK_AX88796L_PORT(port) \
   ((port >= AX88796L_IO_BASE) && (port < (AX88796L_IO_BASE+0x20)))
@@ -112,8 +79,8 @@ unsigned char rts7751r2d_inb(unsigned long port)
                return (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
        else if (PXSEG(port))
                return *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               return *(volatile unsigned char *)PCI_IOMAP(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);
 }
@@ -126,11 +93,12 @@ unsigned char rts7751r2d_inb_p(unsigned long port)
                v = (*(volatile unsigned short *)port88796l(port, 0)) & 0xff;
         else if (PXSEG(port))
                v = *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               v = *(volatile unsigned char *)PCI_IOMAP(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);
-       delay();
+
+       ctrl_delay();
 
        return v;
 }
@@ -138,13 +106,13 @@ unsigned char rts7751r2d_inb_p(unsigned long port)
 unsigned short rts7751r2d_inw(unsigned long port)
 {
        if (CHECK_AX88796L_PORT(port))
-               maybebadio(inw, port);
+               maybebadio(port);
         else if (PXSEG(port))
                return *(volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               return *(volatile unsigned short *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return *(volatile unsigned short *)pci_ioaddr(port);
        else
-               maybebadio(inw, port);
+               maybebadio(port);
 
        return 0;
 }
@@ -152,13 +120,13 @@ unsigned short rts7751r2d_inw(unsigned long port)
 unsigned int rts7751r2d_inl(unsigned long port)
 {
        if (CHECK_AX88796L_PORT(port))
-               maybebadio(inl, port);
+               maybebadio(port);
         else if (PXSEG(port))
                return *(volatile unsigned long *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               return *(volatile unsigned long *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               return *(volatile unsigned long *)pci_ioaddr(port);
        else
-               maybebadio(inl, port);
+               maybebadio(port);
 
        return 0;
 }
@@ -169,8 +137,8 @@ void rts7751r2d_outb(unsigned char value, unsigned long port)
                *((volatile unsigned short *)port88796l(port, 0)) = value;
         else if (PXSEG(port))
                *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(volatile unsigned char *)PCI_IOMAP(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;
 }
@@ -181,143 +149,152 @@ void rts7751r2d_outb_p(unsigned char value, unsigned long port)
                *((volatile unsigned short *)port88796l(port, 0)) = value;
         else if (PXSEG(port))
                *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(volatile unsigned char *)PCI_IOMAP(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;
-       delay();
+
+       ctrl_delay();
 }
 
 void rts7751r2d_outw(unsigned short value, unsigned long port)
 {
        if (CHECK_AX88796L_PORT(port))
-               maybebadio(outw, port);
+               maybebadio(port);
         else if (PXSEG(port))
                *(volatile unsigned short *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(volatile unsigned short *)PCI_IOMAP(port) = value;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               *(volatile unsigned short *)pci_ioaddr(port) = value;
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
 void rts7751r2d_outl(unsigned int value, unsigned long port)
 {
        if (CHECK_AX88796L_PORT(port))
-               maybebadio(outl, port);
+               maybebadio(port);
         else if (PXSEG(port))
                *(volatile unsigned long *)port = value;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               *(volatile unsigned long *)PCI_IOMAP(port) = value;
+       else if (is_pci_ioaddr(port) || shifted_port(port))
+               *(volatile unsigned long *)pci_ioaddr(port) = value;
        else
-               maybebadio(outl, port);
+               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;
-       unsigned char *s = addr;
 
        if (CHECK_AX88796L_PORT(port)) {
                p = (volatile unsigned short *)port88796l(port, 0);
-               while (count--) *s++ = *p & 0xff;
+               while (count--)
+                       ctrl_outb(*p & 0xff, a++);
        } else if (PXSEG(port))
-               while (count--) *s++ = *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               bp = (__u8 *)PCI_IOMAP(port);
-               while (count--) *s++ = *bp;
+               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--) *s++ = *p & 0xff;
+               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;
-       __u16 *s = addr;
 
        if (CHECK_AX88796L_PORT(port))
                p = (volatile unsigned short *)port88796l(port, 1);
        else if (PXSEG(port))
                p = (volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               p = (volatile unsigned short *)PCI_IOMAP(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--) *s++ = *p;
+       while (count--)
+               ctrl_outw(*p, a++);
 }
 
 void rts7751r2d_insl(unsigned long port, void *addr, unsigned long count)
 {
        if (CHECK_AX88796L_PORT(port))
-               maybebadio(insl, port);
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
-               __u32 *s = addr;
-
-               while (count--) *s++ = *p;
+               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(insl, port);
+               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;
-       const __u8 *s = addr;
 
        if (CHECK_AX88796L_PORT(port)) {
                p = (volatile unsigned short *)port88796l(port, 0);
-               while (count--) *p = *s++;
+               while (count--)
+                       *p = ctrl_inb(a++);
        } else if (PXSEG(port))
-               while (count--) *(volatile unsigned char *)port = *s++;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               bp = (__u8 *)PCI_IOMAP(port);
-               while (count--) *bp = *s++;
+               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 = *s++;
+               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;
-       const __u16 *s = addr;
 
        if (CHECK_AX88796L_PORT(port))
                p = (volatile unsigned short *)port88796l(port, 1);
        else if (PXSEG(port))
                p = (volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port))
-               p = (volatile unsigned short *)PCI_IOMAP(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--) *p = *s++;
+
+       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(outsl, port);
-       else if (CHECK_SH7751_PCIIO(port) || shifted_port(port)) {
-               volatile __u32 *p = (__u32 *)PCI_IOMAP(port);
-               const __u32 *s = addr;
-
-               while (count--) *p = *s++;
+               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(outsl, port);
-}
-
-void *rts7751r2d_ioremap(unsigned long offset, unsigned long size)
-{
-       if (offset >= 0xfd000000)
-               return (void *)offset;
-       else
-               return (void *)P2SEGADDR(offset);
+               maybebadio(port);
 }
-EXPORT_SYMBOL(rts7751r2d_ioremap);
 
 unsigned long rts7751r2d_isa_port2addr(unsigned long offset)
 {
index 154535440bbf7a626c76272e6b9c9ed36545c45b..c915e7a3693a0648b8f52e090cdc4add9b72ac09 100644 (file)
@@ -41,30 +41,24 @@ static unsigned int startup_rts7751r2d_irq(unsigned int irq)
 
 static void disable_rts7751r2d_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short val;
        unsigned short mask = 0xffff ^ (0x0001 << mask_pos[irq]);
 
        /* Set the priority in IPR to 0 */
-       local_irq_save(flags);
        val = ctrl_inw(IRLCNTR1);
        val &= mask;
        ctrl_outw(val, IRLCNTR1);
-       local_irq_restore(flags);
 }
 
 static void enable_rts7751r2d_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short val;
        unsigned short value = (0x0001 << mask_pos[irq]);
 
        /* Set priority in IPR back to original value */
-       local_irq_save(flags);
        val = ctrl_inw(IRLCNTR1);
        val |= value;
        ctrl_outw(val, IRLCNTR1);
-       local_irq_restore(flags);
 }
 
 int rts7751r2d_irq_demux(int irq)
index 4d16de71fac10df3484af2c33cf330f4448c0fa0..e14a13d12d4ad228351b90ee957304275e30bda7 100644 (file)
@@ -12,8 +12,6 @@
 #include <asm/io.h>
 #include <asm/rts7751r2d/rts7751r2d.h>
 
-extern unsigned int debug_counter;
-
 #ifdef CONFIG_HEARTBEAT
 
 #include <linux/sched.h>
@@ -55,12 +53,3 @@ void rts7751r2d_led(unsigned short value)
        ctrl_outw(value, PA_OUTPORT);
 }
 
-void debug_led_disp(void)
-{
-       unsigned short value;
-
-       value = (unsigned short)debug_counter++;
-       rts7751r2d_led(value);
-       if (value == 0xff)
-               debug_counter = 0;
-}
diff --git a/arch/sh/boards/renesas/rts7751r2d/mach.c b/arch/sh/boards/renesas/rts7751r2d/mach.c
deleted file mode 100644 (file)
index 5ed9e97..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_rts7751r2d.c
- *
- * Minor tweak of mach_se.c file to reference rts7751r2d-specific items.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the Renesas Technology sales RTS7751R2D
- */
-
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/irq.h>
-#include <asm/rts7751r2d/io.h>
-
-extern void heartbeat_rts7751r2d(void);
-extern void init_rts7751r2d_IRQ(void);
-extern void *rts7751r2d_ioremap(unsigned long, unsigned long);
-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);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_rts7751r2d __initmv = {
-       .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_ioremap             = rts7751r2d_ioremap,
-       .mv_isa_port2addr       = rts7751r2d_isa_port2addr,
-       .mv_init_irq            = init_rts7751r2d_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_rts7751r2d,
-#endif
-       .mv_irq_demux           = rts7751r2d_irq_demux,
-
-#ifdef CONFIG_USB_OHCI_HCD
-       .mv_consistent_alloc    = voyagergx_consistent_alloc,
-       .mv_consistent_free     = voyagergx_consistent_free,
-#endif
-};
-ALIAS_MV(rts7751r2d)
index 2587fd1a0240ea61deca57837f90dfb16e1230f4..20597a6e6702c40e76f5cab65a2b396f668b3c08 100644 (file)
 /*
- * linux/arch/sh/kernel/setup_rts7751r2d.c
- *
- * Copyright (C) 2000  Kazumoto Kojima
- *
  * Renesas Technology Sales RTS7751R2D Support.
  *
- * Modified for RTS7751R2D by
- * Atom Create Engineering Co., Ltd. 2002.
+ * Copyright (C) 2002 Atom Create Engineering Co., Ltd.
+ * Copyright (C) 2004 - 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/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/pm.h>
 #include <asm/io.h>
-#include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/machvec.h>
+#include <asm/mach/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,
+       },
+};
+
+static void __init voyagergx_serial_init(void)
+{
+       unsigned long val;
+
+       /*
+        * GPIO Control
+        */
+       val = inl(GPIO_MUX_HIGH);
+       val |= 0x00001fe0;
+       outl(val, GPIO_MUX_HIGH);
+
+       /*
+        * Power Mode Gate
+        */
+       val = inl(POWER_MODE0_GATE);
+       val |= (POWER_MODE0_GATE_U0 | POWER_MODE0_GATE_U1);
+       outl(val, POWER_MODE0_GATE);
+
+       val = inl(POWER_MODE1_GATE);
+       val |= (POWER_MODE1_GATE_U0 | POWER_MODE1_GATE_U1);
+       outl(val, POWER_MODE1_GATE);
+}
+
+static struct platform_device uart_device = {
+       .name           = "serial8250",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = uart_platform_data,
+       },
+};
+
+static struct platform_device *rts7751r2d_devices[] __initdata = {
+       &uart_device,
+};
 
-unsigned int debug_counter;
+static int __init rts7751r2d_devices_setup(void)
+{
+       return platform_add_devices(rts7751r2d_devices,
+                                   ARRAY_SIZE(rts7751r2d_devices));
+}
 
-const char *get_system_type(void)
+static void rts7751r2d_power_off(void)
 {
-       return "RTS7751R2D";
+       ctrl_outw(0x0001, PA_POWOFF);
 }
 
 /*
  * Initialize the board
  */
-void __init platform_setup(void)
+static void __init rts7751r2d_setup(char **cmdline_p)
 {
-       printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
+       device_initcall(rts7751r2d_devices_setup);
+
        ctrl_outw(0x0000, PA_OUTPORT);
-       debug_counter = 0;
+       pm_power_off = rts7751r2d_power_off;
+
+       voyagergx_serial_init();
+
+       printk(KERN_INFO "Renesas Technology Sales RTS7751R2D support.\n");
 }
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_rts7751r2d __initmv = {
+       .mv_name                = "RTS7751R2D",
+       .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
+       .mv_consistent_alloc    = voyagergx_consistent_alloc,
+       .mv_consistent_free     = voyagergx_consistent_free,
+#endif
+};
+ALIAS_MV(rts7751r2d)
diff --git a/arch/sh/boards/renesas/sh7710voipgw/Makefile b/arch/sh/boards/renesas/sh7710voipgw/Makefile
new file mode 100644 (file)
index 0000000..7703756
--- /dev/null
@@ -0,0 +1 @@
+obj-y   := setup.o
diff --git a/arch/sh/boards/renesas/sh7710voipgw/setup.c b/arch/sh/boards/renesas/sh7710voipgw/setup.c
new file mode 100644 (file)
index 0000000..e57e7af
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Renesas Technology SH7710 VoIP Gateway
+ *
+ * Copyright (C) 2006  Ranjit Deshpande
+ * Kenati Technologies Inc.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+#include <linux/init.h>
+#include <asm/machvec.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+/*
+ * Initialize IRQ setting
+ */
+static void __init sh7710voipgw_init_irq(void)
+{
+       /* Disable all interrupts in IPR registers */
+       ctrl_outw(0x0, INTC_IPRA);
+       ctrl_outw(0x0, INTC_IPRB);
+       ctrl_outw(0x0, INTC_IPRC);
+       ctrl_outw(0x0, INTC_IPRD);
+       ctrl_outw(0x0, INTC_IPRE);
+       ctrl_outw(0x0, INTC_IPRF);
+       ctrl_outw(0x0, INTC_IPRG);
+       ctrl_outw(0x0, INTC_IPRH);
+       ctrl_outw(0x0, INTC_IPRI);
+
+       /* Ack all interrupt sources in the IRR0 register */
+       ctrl_outb(0x3f, INTC_IRR0);
+
+       /* Use IRQ0 - IRQ3 as active low interrupt lines i.e. disable
+        * IRL mode.
+        */
+       ctrl_outw(0x2aa, INTC_ICR1);
+
+       /* Now make IPR interrupts */
+       make_ipr_irq(TIMER2_IRQ, TIMER2_IPR_ADDR,
+                       TIMER2_IPR_POS, TIMER2_PRIORITY);
+       make_ipr_irq(WDT_IRQ, WDT_IPR_ADDR, WDT_IPR_POS, WDT_PRIORITY);
+
+       /* SCIF0 */
+       make_ipr_irq(SCIF0_ERI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+                       SCIF0_PRIORITY);
+       make_ipr_irq(SCIF0_RXI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+                       SCIF0_PRIORITY);
+       make_ipr_irq(SCIF0_BRI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+                       SCIF0_PRIORITY);
+       make_ipr_irq(SCIF0_TXI_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS,
+                       SCIF0_PRIORITY);
+
+       /* DMAC-1 */
+       make_ipr_irq(DMTE0_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+       make_ipr_irq(DMTE1_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+       make_ipr_irq(DMTE2_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+       make_ipr_irq(DMTE3_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
+
+       /* DMAC-2 */
+       make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+       make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+
+       /* IPSEC */
+       make_ipr_irq(IPSEC_IRQ, IPSEC_IPR_ADDR, IPSEC_IPR_POS, IPSEC_PRIORITY);
+
+       /* EDMAC */
+       make_ipr_irq(EDMAC0_IRQ, EDMAC0_IPR_ADDR, EDMAC0_IPR_POS,
+                       EDMAC0_PRIORITY);
+       make_ipr_irq(EDMAC1_IRQ, EDMAC1_IPR_ADDR, EDMAC1_IPR_POS,
+                       EDMAC1_PRIORITY);
+       make_ipr_irq(EDMAC2_IRQ, EDMAC2_IPR_ADDR, EDMAC2_IPR_POS,
+                       EDMAC2_PRIORITY);
+
+       /* SIOF0 */
+       make_ipr_irq(SIOF0_ERI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+                       SIOF0_PRIORITY);
+       make_ipr_irq(SIOF0_TXI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+                       SIOF0_PRIORITY);
+       make_ipr_irq(SIOF0_RXI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+                       SIOF0_PRIORITY);
+       make_ipr_irq(SIOF0_CCI_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS,
+                       SIOF0_PRIORITY);
+
+       /* SIOF1 */
+       make_ipr_irq(SIOF1_ERI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+                       SIOF1_PRIORITY);
+       make_ipr_irq(SIOF1_TXI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+                       SIOF1_PRIORITY);
+       make_ipr_irq(SIOF1_RXI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+                       SIOF1_PRIORITY);
+       make_ipr_irq(SIOF1_CCI_IRQ, SIOF1_IPR_ADDR, SIOF1_IPR_POS,
+                       SIOF1_PRIORITY);
+
+       /* SLIC IRQ's */
+       make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY);
+       make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY);
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_sh7710voipgw __initmv = {
+       .mv_name                = "SH7710 VoIP Gateway",
+       .mv_nr_irqs             = 104,
+       .mv_init_irq            = sh7710voipgw_init_irq,
+};
+ALIAS_MV(sh7710voipgw)
index cf979011aa943de88bda3d9d01daf0628706e4a0..cde6e5d192c417475286380ac46dcb32c7f39ca3 100644 (file)
@@ -5,66 +5,25 @@
  * Based largely on io_se.c.
  *
  * I/O routine for Hitachi 7751 Systemh.
- *
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <asm/systemh/7751systemh.h>
+#include <linux/pci.h>
+#include <asm/systemh7751.h>
 #include <asm/addrspace.h>
 #include <asm/io.h>
 
-#include <linux/pci.h>
-#include "../../drivers/pci/pci-sh7751.h"
-
-/*
- * The 7751 SystemH Engine uses the built-in PCI controller (PCIC)
- * of the 7751 processor, and has a SuperIO accessible on its memory
- * bus.
- */
-
-#define PCIIOBR                (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA    SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA   SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
 #define ETHER_IOMAP(adr) (0xB3000000 + (adr)) /*map to 16bits access area
                                                 of smc lan chip*/
-
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
 static inline volatile __u16 *
 port2adr(unsigned int port)
 {
        if (port >= 0x2000)
                return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
-#if 0
-       else
-               return (volatile __u16 *) (PA_SUPERIO + (port << 1));
-#endif
-       maybebadio(name,(unsigned long)port);
+       maybebadio((unsigned long)port);
        return (volatile __u16*)port;
 }
 
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
-  ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(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)
@@ -76,8 +35,8 @@ unsigned char sh7751systemh_inb(unsigned long port)
 {
        if (PXSEG(port))
                return *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               return *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               return *(volatile unsigned char *)pci_ioaddr(port);
        else if (port <= 0x3F1)
                return *(volatile unsigned char *)ETHER_IOMAP(port);
        else
@@ -90,13 +49,13 @@ unsigned char sh7751systemh_inb_p(unsigned long port)
 
         if (PXSEG(port))
                 v = *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                v = *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                v = *(volatile unsigned char *)pci_ioaddr(port);
        else if (port <= 0x3F1)
                v = *(volatile unsigned char *)ETHER_IOMAP(port);
        else
                v = (*port2adr(port))&0xff;
-       delay();
+       ctrl_delay();
        return v;
 }
 
@@ -104,14 +63,14 @@ unsigned short sh7751systemh_inw(unsigned long port)
 {
         if (PXSEG(port))
                 return *(volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                return *(volatile unsigned short *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                return *(volatile unsigned short *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else if (port <= 0x3F1)
                return *(volatile unsigned int *)ETHER_IOMAP(port);
        else
-               maybebadio(inw, port);
+               maybebadio(port);
        return 0;
 }
 
@@ -119,14 +78,14 @@ unsigned int sh7751systemh_inl(unsigned long port)
 {
         if (PXSEG(port))
                 return *(volatile unsigned long *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                return *(volatile unsigned int *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                return *(volatile unsigned int *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else if (port <= 0x3F1)
                return *(volatile unsigned int *)ETHER_IOMAP(port);
        else
-               maybebadio(inl, port);
+               maybebadio(port);
        return 0;
 }
 
@@ -135,8 +94,8 @@ void sh7751systemh_outb(unsigned char value, unsigned long port)
 
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else if (port <= 0x3F1)
                *(volatile unsigned char *)ETHER_IOMAP(port) = value;
        else
@@ -147,37 +106,37 @@ void sh7751systemh_outb_p(unsigned char value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else if (port <= 0x3F1)
                *(volatile unsigned char *)ETHER_IOMAP(port) = value;
        else
                *(port2adr(port)) = value;
-       delay();
+       ctrl_delay();
 }
 
 void sh7751systemh_outw(unsigned short value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned short *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned short *)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned short *)pci_ioaddr(port)) = value;
        else if (port >= 0x2000)
                *port2adr(port) = value;
        else if (port <= 0x3F1)
                *(volatile unsigned short *)ETHER_IOMAP(port) = value;
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
 void sh7751systemh_outl(unsigned int value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned long *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned long*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned long*)pci_ioaddr(port)) = value;
        else
-               maybebadio(outl, port);
+               maybebadio(port);
 }
 
 void sh7751systemh_insb(unsigned long port, void *addr, unsigned long count)
@@ -194,7 +153,7 @@ void sh7751systemh_insw(unsigned long port, void *addr, unsigned long count)
 
 void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count)
 {
-       maybebadio(insl, port);
+       maybebadio(port);
 }
 
 void sh7751systemh_outsb(unsigned long port, const void *addr, unsigned long count)
@@ -211,73 +170,5 @@ void sh7751systemh_outsw(unsigned long port, const void *addr, unsigned long cou
 
 void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count)
 {
-       maybebadio(outsw, port);
-}
-
-/* For read/write calls, just copy generic (pass-thru); PCIMBR is  */
-/* already set up.  For a larger memory space, these would need to */
-/* reset PCIMBR as needed on a per-call basis...                   */
-
-unsigned char sh7751systemh_readb(unsigned long addr)
-{
-       return *(volatile unsigned char*)addr;
-}
-
-unsigned short sh7751systemh_readw(unsigned long addr)
-{
-       return *(volatile unsigned short*)addr;
-}
-
-unsigned int sh7751systemh_readl(unsigned long addr)
-{
-       return *(volatile unsigned long*)addr;
-}
-
-void sh7751systemh_writeb(unsigned char b, unsigned long addr)
-{
-       *(volatile unsigned char*)addr = b;
-}
-
-void sh7751systemh_writew(unsigned short b, unsigned long addr)
-{
-       *(volatile unsigned short*)addr = b;
-}
-
-void sh7751systemh_writel(unsigned int b, unsigned long addr)
-{
-        *(volatile unsigned long*)addr = b;
-}
-
-\f
-
-/* Map ISA bus address to the real address. Only for PCMCIA.  */
-
-/* ISA page descriptor.  */
-static __u32 sh_isa_memmap[256];
-
-#if 0
-static int
-sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
-       int idx;
-
-       if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
-               return -1;
-
-       idx = start >> 12;
-       sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
-       printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
-              start, length, offset, idx, sh_isa_memmap[idx]);
-       return 0;
-}
-#endif
-
-unsigned long
-sh7751systemh_isa_port2addr(unsigned long offset)
-{
-       int idx;
-
-       idx = (offset >> 12) & 0xff;
-       offset &= 0xfff;
-       return sh_isa_memmap[idx] + offset;
+       maybebadio(port);
 }
index 8372d967f60120f249e71c0135578ca36459da04..8d016dae23334731a15564e2a64fad25a7665091 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <asm/io.h>
-#include <asm/mach/7751systemh.h>
+#include <asm/systemh7751.h>
 #include <asm/smc37c93x.h>
 
 /* address of external interrupt mask register
@@ -57,12 +57,9 @@ static void shutdown_systemh_irq(unsigned int irq)
 static void disable_systemh_irq(unsigned int irq)
 {
        if (systemh_irq_mask_register) {
-               unsigned long flags;
                unsigned long val, mask = 0x01 << 1;
 
                /* Clear the "irq"th bit in the mask and set it in the request */
-               local_irq_save(flags);
-
                val = ctrl_inl((unsigned long)systemh_irq_mask_register);
                val &= ~mask;
                ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
@@ -70,23 +67,18 @@ static void disable_systemh_irq(unsigned int irq)
                val = ctrl_inl((unsigned long)systemh_irq_request_register);
                val |= mask;
                ctrl_outl(val, (unsigned long)systemh_irq_request_register);
-
-               local_irq_restore(flags);
        }
 }
 
 static void enable_systemh_irq(unsigned int irq)
 {
        if (systemh_irq_mask_register) {
-               unsigned long flags;
                unsigned long val, mask = 0x01 << 1;
 
                /* Set "irq"th bit in the mask register */
-               local_irq_save(flags);
                val = ctrl_inl((unsigned long)systemh_irq_mask_register);
                val |= mask;
                ctrl_outl(val, (unsigned long)systemh_irq_mask_register);
-               local_irq_restore(flags);
        }
 }
 
index 826fa3d7669c7952fee3655d8b7c126077a297b6..a8467bf90c2515d00df03feb1926931e9e7321f3 100644 (file)
  * for more details.
  */
 #include <linux/init.h>
-#include <asm/mach/7751systemh.h>
-#include <asm/mach/io.h>
 #include <asm/machvec.h>
+#include <asm/systemh7751.h>
 
 extern void make_systemh_irq(unsigned int irq);
 
-const char *get_system_type(void)
-{
-       return "7751 SystemH";
-}
-
 /*
  * Initialize IRQ setting
  */
-void __init init_7751systemh_IRQ(void)
+static void __init sh7751systemh_init_irq(void)
 {
-/*     make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); LAN */
-/*     make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-4); */
        make_systemh_irq(0xb);  /* Ethernet interrupt */
 }
 
 struct sh_machine_vector mv_7751systemh __initmv = {
+       .mv_name                = "7751 SystemH",
        .mv_nr_irqs             = 72,
 
        .mv_inb                 = sh7751systemh_inb,
@@ -60,21 +53,6 @@ struct sh_machine_vector mv_7751systemh __initmv = {
        .mv_outsw               = sh7751systemh_outsw,
        .mv_outsl               = sh7751systemh_outsl,
 
-       .mv_readb               = sh7751systemh_readb,
-       .mv_readw               = sh7751systemh_readw,
-       .mv_readl               = sh7751systemh_readl,
-       .mv_writeb              = sh7751systemh_writeb,
-       .mv_writew              = sh7751systemh_writew,
-       .mv_writel              = sh7751systemh_writel,
-
-       .mv_isa_port2addr       = sh7751systemh_isa_port2addr,
-
-       .mv_init_irq            = init_7751systemh_IRQ,
+       .mv_init_irq            = sh7751system_init_irq,
 };
 ALIAS_MV(7751systemh)
-
-int __init platform_setup(void)
-{
-       return 0;
-}
-
index bea6c572ad82a805a28fd6ae51e185d6d3e0e421..a3a37c9aad2eea672bd36a9d9665b7ffdb0521f2 100644 (file)
@@ -9,22 +9,17 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-
 #include <asm/io.h>
 #include <asm/machvec.h>
 #include <asm/mach/io.h>
 
 extern int saturn_irq_demux(int irq_nr);
 
-const char *get_system_type(void)
-{
-       return "Sega Saturn";
-}
-
 /*
  * The Machine Vector
  */
 struct sh_machine_vector mv_saturn __initmv = {
+       .mv_name                = "Sega Saturn",
        .mv_nr_irqs             = 80,   /* Fix this later */
 
        .mv_isa_port2addr       = saturn_isa_port2addr,
@@ -33,11 +28,4 @@ struct sh_machine_vector mv_saturn __initmv = {
        .mv_ioremap             = saturn_ioremap,
        .mv_iounmap             = saturn_iounmap,
 };
-
 ALIAS_MV(saturn)
-
-int __init platform_setup(void)
-{
-       return 0;
-}
-
index f449a94ddffde4822cc037ba5677c78627b106d0..8a03d7a52a7ca441ecf24bcc2d6f57e15bcd0be1 100644 (file)
@@ -9,8 +9,8 @@
  */
 
 #include <linux/kernel.h>
-#include <asm/mach/se7300.h>
 #include <asm/io.h>
+#include <asm/se7300.h>
 
 #define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
 
@@ -99,6 +99,7 @@ bad_outb(struct iop *p, unsigned char value, unsigned long port)
        badio(inw, port);
 }
 
+#ifdef CONFIG_SMC91X
 /* MSTLANEX01 LAN at 0xb400:0000 */
 static struct iop laniop = {
        .start = 0x300,
@@ -110,6 +111,7 @@ static struct iop laniop = {
        .outb = simple_outb,
        .outw = simple_outw,
 };
+#endif
 
 /* NE2000 pc card NIC */
 static struct iop neiop = {
@@ -123,6 +125,7 @@ static struct iop neiop = {
        .outw = simple_outw,
 };
 
+#ifdef CONFIG_IDE
 /* CF in CF slot */
 static struct iop cfiop = {
        .base = 0xb0600000,
@@ -132,12 +135,13 @@ static struct iop cfiop = {
        .outb = pcc_outb,
        .outw = simple_outw,
 };
+#endif
 
 static __inline__ struct iop *
 port2iop(unsigned long port)
 {
        if (0) ;
-#if defined(CONFIG_SMC91111)
+#if defined(CONFIG_SMC91X)
        else if (laniop.check(&laniop, port))
                return &laniop;
 #endif
index 216a78d1a108c26c3ff4ab1cc0b74e7cfd958a00..ad1034f98a293ba4dfeb0259369538458e299f83 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/irq.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/mach/se7300.h>
+#include <asm/se7300.h>
 
 /*
  * Initialize IRQ setting
index ad51f0a9c1e31999041ac59b5e408679bee4dcba..4d03bb7774be781dcf5c3a599a603b3134389970 100644 (file)
  */
 
 #include <linux/sched.h>
-#include <asm/mach/se7300.h>
-
-static void
-mach_led(int position, int value)
-{
-       volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-
-       if (value) {
-               *p |= (1 << 8);
-       } else {
-               *p &= ~(1 << 8);
-       }
-}
-
+#include <asm/se7300.h>
 
 /* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void
-heartbeat_7300se(void)
+void heartbeat_7300se(void)
 {
        static unsigned int cnt = 0, period = 0;
        volatile unsigned short *p = (volatile unsigned short *) PA_LED;
index ebcd98d4c0818601535bfb52e051004d7579a9e7..6f082a722d42842f5502ff9b0a7497f3f35fd659 100644 (file)
@@ -9,23 +9,16 @@
 
 #include <linux/init.h>
 #include <asm/machvec.h>
-#include <asm/machvec_init.h>
-#include <asm/mach/io.h>
+#include <asm/se7300.h>
 
 void heartbeat_7300se(void);
 void init_7300se_IRQ(void);
 
-const char *
-get_system_type(void)
-{
-       return "SolutionEngine 7300";
-}
-
 /*
  * The Machine Vector
  */
-
 struct sh_machine_vector mv_7300se __initmv = {
+       .mv_name = "SolutionEngine 7300",
        .mv_nr_irqs = 109,
        .mv_inb = sh7300se_inb,
        .mv_inw = sh7300se_inw,
@@ -53,13 +46,4 @@ struct sh_machine_vector mv_7300se __initmv = {
        .mv_heartbeat = heartbeat_7300se,
 #endif
 };
-
 ALIAS_MV(7300se)
-/*
- * Initialize the board
- */
-void __init
-platform_setup(void)
-{
-
-}
index 755df5ac4a4e81c1d6c12341a60b79ec51a58ead..72715575458b81b2f217738d2fb6dd0df0bb8566 100644 (file)
@@ -99,6 +99,7 @@ bad_outb(struct iop *p, unsigned char value, unsigned long port)
        badio(inw, port);
 }
 
+#ifdef CONFIG_SMC91X
 /* MSTLANEX01 LAN at 0xb400:0000 */
 static struct iop laniop = {
        .start = 0x300,
@@ -110,6 +111,7 @@ static struct iop laniop = {
        .outb = simple_outb,
        .outw = simple_outw,
 };
+#endif
 
 /* NE2000 pc card NIC */
 static struct iop neiop = {
@@ -123,6 +125,7 @@ static struct iop neiop = {
        .outw = simple_outw,
 };
 
+#ifdef CONFIG_IDE
 /* CF in CF slot */
 static struct iop cfiop = {
        .base = 0xb0600000,
@@ -132,12 +135,13 @@ static struct iop cfiop = {
        .outb = pcc_outb,
        .outw = simple_outw,
 };
+#endif
 
 static __inline__ struct iop *
 port2iop(unsigned long port)
 {
        if (0) ;
-#if defined(CONFIG_SMC91111)
+#if defined(CONFIG_SMC91X)
        else if (laniop.check(&laniop, port))
                return &laniop;
 #endif
index 4344d0ef24aa05ea8845632e8996bb3d15f570c7..2c62b8ea350ee8e3d214ed9de51b31d920035f7a 100644 (file)
@@ -7,7 +7,6 @@
  * Modified for SH-Mobile SolutionEngine 73180 Support
  *              by YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
  *
- *
  */
 
 #include <linux/init.h>
 #include <asm/io.h>
 #include <asm/mach/se73180.h>
 
-static int
-intreq2irq(int i)
-{
-       if (i == 5)
-               return 10;
-       return 32 + 7 - i;
-}
-
 static int
 irq2intreq(int irq)
 {
index 610439fde6ee5f3fc6ef7ece6e3be5455a41301f..4b72e9a3ead9ba7a1fa41739c72d6bd66fa275ae 100644 (file)
 #include <linux/sched.h>
 #include <asm/mach/se73180.h>
 
-static void
-mach_led(int position, int value)
-{
-       volatile unsigned short *p = (volatile unsigned short *) PA_LED;
-
-       if (value) {
-               *p |= (1 << LED_SHIFT);
-       } else {
-               *p &= ~(1 << LED_SHIFT);
-       }
-}
-
 /* Cycle the LED's in the clasic Knightrider/Sun pattern */
-void
-heartbeat_73180se(void)
+void heartbeat_73180se(void)
 {
        static unsigned int cnt = 0, period = 0;
        volatile unsigned short *p = (volatile unsigned short *) PA_LED;
index cdb7b5f8d942f7cf1520aa16c7661d95b6a4b142..b38ef50a160a2114b4c7a290d420797de3871e12 100644 (file)
 
 #include <linux/init.h>
 #include <asm/machvec.h>
-#include <asm/machvec_init.h>
-#include <asm/mach/io.h>
+#include <asm/se73180.h>
+#include <asm/irq.h>
 
 void heartbeat_73180se(void);
 void init_73180se_IRQ(void);
 
-const char *
-get_system_type(void)
-{
-       return "SolutionEngine 73180";
-}
-
 /*
  * The Machine Vector
  */
-
 struct sh_machine_vector mv_73180se __initmv = {
+       .mv_name = "SolutionEngine 73180",
        .mv_nr_irqs = 108,
        .mv_inb = sh73180se_inb,
        .mv_inw = sh73180se_inw,
@@ -51,17 +45,9 @@ struct sh_machine_vector mv_73180se __initmv = {
        .mv_outsl = sh73180se_outsl,
 
        .mv_init_irq = init_73180se_IRQ,
+       .mv_irq_demux = shmse_irq_demux,
 #ifdef CONFIG_HEARTBEAT
        .mv_heartbeat = heartbeat_73180se,
 #endif
 };
-
 ALIAS_MV(73180se)
-/*
- * Initialize the board
- */
-void __init
-platform_setup(void)
-{
-
-}
diff --git a/arch/sh/boards/se/7343/Makefile b/arch/sh/boards/se/7343/Makefile
new file mode 100644 (file)
index 0000000..4291069
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the 7343 SolutionEngine specific parts of the kernel
+#
+
+obj-y   := setup.o io.o irq.o
+
+obj-$(CONFIG_HEARTBEAT) += led.o
diff --git a/arch/sh/boards/se/7343/io.c b/arch/sh/boards/se/7343/io.c
new file mode 100644 (file)
index 0000000..646661a
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * arch/sh/boards/se/7343/io.c
+ *
+ * I/O routine for SH-Mobile3AS 7343 SolutionEngine.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/mach/se7343.h>
+
+#define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
+
+struct iop {
+       unsigned long start, end;
+       unsigned long base;
+       struct iop *(*check) (struct iop * p, unsigned long port);
+       unsigned char (*inb) (struct iop * p, unsigned long port);
+       unsigned short (*inw) (struct iop * p, unsigned long port);
+       void (*outb) (struct iop * p, unsigned char value, unsigned long port);
+       void (*outw) (struct iop * p, unsigned short value, unsigned long port);
+};
+
+struct iop *
+simple_check(struct iop *p, unsigned long port)
+{
+       static int count;
+
+       if (count < 100)
+               count++;
+
+       port &= 0xFFFF;
+
+       if ((p->start <= port) && (port <= p->end))
+               return p;
+       else
+               badio(check, port);
+}
+
+struct iop *
+ide_check(struct iop *p, unsigned long port)
+{
+       if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7))
+               return p;
+       return NULL;
+}
+
+unsigned char
+simple_inb(struct iop *p, unsigned long port)
+{
+       return *(unsigned char *) (p->base + port);
+}
+
+unsigned short
+simple_inw(struct iop *p, unsigned long port)
+{
+       return *(unsigned short *) (p->base + port);
+}
+
+void
+simple_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+       *(unsigned char *) (p->base + port) = value;
+}
+
+void
+simple_outw(struct iop *p, unsigned short value, unsigned long port)
+{
+       *(unsigned short *) (p->base + port) = value;
+}
+
+unsigned char
+pcc_inb(struct iop *p, unsigned long port)
+{
+       unsigned long addr = p->base + port + 0x40000;
+       unsigned long v;
+
+       if (port & 1)
+               addr += 0x00400000;
+       v = *(volatile unsigned char *) addr;
+       return v;
+}
+
+void
+pcc_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+       unsigned long addr = p->base + port + 0x40000;
+
+       if (port & 1)
+               addr += 0x00400000;
+       *(volatile unsigned char *) addr = value;
+}
+
+unsigned char
+bad_inb(struct iop *p, unsigned long port)
+{
+       badio(inb, port);
+}
+
+void
+bad_outb(struct iop *p, unsigned char value, unsigned long port)
+{
+       badio(inw, port);
+}
+
+#ifdef CONFIG_SMC91X
+/* MSTLANEX01 LAN at 0xb400:0000 */
+static struct iop laniop = {
+       .start = 0x00,
+       .end = 0x0F,
+       .base = 0x04000000,
+       .check = simple_check,
+       .inb = simple_inb,
+       .inw = simple_inw,
+       .outb = simple_outb,
+       .outw = simple_outw,
+};
+#endif
+
+#ifdef CONFIG_NE2000
+/* NE2000 pc card NIC */
+static struct iop neiop = {
+       .start = 0x280,
+       .end = 0x29f,
+       .base = 0xb0600000 + 0x80,      /* soft 0x280 -> hard 0x300 */
+       .check = simple_check,
+       .inb = pcc_inb,
+       .inw = simple_inw,
+       .outb = pcc_outb,
+       .outw = simple_outw,
+};
+#endif
+
+#ifdef CONFIG_IDE
+/* CF in CF slot */
+static struct iop cfiop = {
+       .base = 0xb0600000,
+       .check = ide_check,
+       .inb = pcc_inb,
+       .inw = simple_inw,
+       .outb = pcc_outb,
+       .outw = simple_outw,
+};
+#endif
+
+static __inline__ struct iop *
+port2iop(unsigned long port)
+{
+       if (0) ;
+#if defined(CONFIG_SMC91X)
+       else if (laniop.check(&laniop, port))
+               return &laniop;
+#endif
+#if defined(CONFIG_NE2000)
+       else if (neiop.check(&neiop, port))
+               return &neiop;
+#endif
+#if defined(CONFIG_IDE)
+       else if (cfiop.check(&cfiop, port))
+               return &cfiop;
+#endif
+       else
+               return NULL;
+}
+
+static inline void
+delay(void)
+{
+       ctrl_inw(0xac000000);
+       ctrl_inw(0xac000000);
+}
+
+unsigned char
+sh7343se_inb(unsigned long port)
+{
+       struct iop *p = port2iop(port);
+       return (p->inb) (p, port);
+}
+
+unsigned char
+sh7343se_inb_p(unsigned long port)
+{
+       unsigned char v = sh7343se_inb(port);
+       delay();
+       return v;
+}
+
+unsigned short
+sh7343se_inw(unsigned long port)
+{
+       struct iop *p = port2iop(port);
+       return (p->inw) (p, port);
+}
+
+unsigned int
+sh7343se_inl(unsigned long port)
+{
+       badio(inl, port);
+}
+
+void
+sh7343se_outb(unsigned char value, unsigned long port)
+{
+       struct iop *p = port2iop(port);
+       (p->outb) (p, value, port);
+}
+
+void
+sh7343se_outb_p(unsigned char value, unsigned long port)
+{
+       sh7343se_outb(value, port);
+       delay();
+}
+
+void
+sh7343se_outw(unsigned short value, unsigned long port)
+{
+       struct iop *p = port2iop(port);
+       (p->outw) (p, value, port);
+}
+
+void
+sh7343se_outl(unsigned int value, unsigned long port)
+{
+       badio(outl, port);
+}
+
+void
+sh7343se_insb(unsigned long port, void *addr, unsigned long count)
+{
+       unsigned char *a = addr;
+       struct iop *p = port2iop(port);
+       while (count--)
+               *a++ = (p->inb) (p, port);
+}
+
+void
+sh7343se_insw(unsigned long port, void *addr, unsigned long count)
+{
+       unsigned short *a = addr;
+       struct iop *p = port2iop(port);
+       while (count--)
+               *a++ = (p->inw) (p, port);
+}
+
+void
+sh7343se_insl(unsigned long port, void *addr, unsigned long count)
+{
+       badio(insl, port);
+}
+
+void
+sh7343se_outsb(unsigned long port, const void *addr, unsigned long count)
+{
+       unsigned char *a = (unsigned char *) addr;
+       struct iop *p = port2iop(port);
+       while (count--)
+               (p->outb) (p, *a++, port);
+}
+
+void
+sh7343se_outsw(unsigned long port, const void *addr, unsigned long count)
+{
+       unsigned short *a = (unsigned short *) addr;
+       struct iop *p = port2iop(port);
+       while (count--)
+               (p->outw) (p, *a++, port);
+}
+
+void
+sh7343se_outsl(unsigned long port, const void *addr, unsigned long count)
+{
+       badio(outsw, port);
+}
diff --git a/arch/sh/boards/se/7343/irq.c b/arch/sh/boards/se/7343/irq.c
new file mode 100644 (file)
index 0000000..b41e3d4
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * arch/sh/boards/se/7343/irq.c
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mach/se7343.h>
+
+static void
+disable_intreq_irq(unsigned int irq)
+{
+       int bit = irq - OFFCHIP_IRQ_BASE;
+       u16 val;
+
+       val = ctrl_inw(PA_CPLD_IMSK);
+       val |= 1 << bit;
+       ctrl_outw(val, PA_CPLD_IMSK);
+}
+
+static void
+enable_intreq_irq(unsigned int irq)
+{
+       int bit = irq - OFFCHIP_IRQ_BASE;
+       u16 val;
+
+       val = ctrl_inw(PA_CPLD_IMSK);
+       val &= ~(1 << bit);
+       ctrl_outw(val, PA_CPLD_IMSK);
+}
+
+static void
+mask_and_ack_intreq_irq(unsigned int irq)
+{
+       disable_intreq_irq(irq);
+}
+
+static unsigned int
+startup_intreq_irq(unsigned int irq)
+{
+       enable_intreq_irq(irq);
+       return 0;
+}
+
+static void
+shutdown_intreq_irq(unsigned int irq)
+{
+       disable_intreq_irq(irq);
+}
+
+static void
+end_intreq_irq(unsigned int irq)
+{
+       if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+               enable_intreq_irq(irq);
+}
+
+static struct hw_interrupt_type intreq_irq_type = {
+       .typename = "FPGA-IRQ",
+       .startup = startup_intreq_irq,
+       .shutdown = shutdown_intreq_irq,
+       .enable = enable_intreq_irq,
+       .disable = disable_intreq_irq,
+       .ack = mask_and_ack_intreq_irq,
+       .end = end_intreq_irq
+};
+
+static void
+make_intreq_irq(unsigned int irq)
+{
+       disable_irq_nosync(irq);
+       irq_desc[irq].handler = &intreq_irq_type;
+       disable_intreq_irq(irq);
+}
+
+int
+shmse_irq_demux(int irq)
+{
+       int bit;
+       volatile u16 val;
+
+       if (irq == IRQ5_IRQ) {
+               /* Read status Register */
+               val = ctrl_inw(PA_CPLD_ST);
+               bit = ffs(val);
+               if (bit != 0)
+                       return OFFCHIP_IRQ_BASE + bit - 1;
+       }
+       return irq;
+}
+
+/* IRQ5 is multiplexed between the following sources:
+ * 1. PC Card socket
+ * 2. Extension slot
+ * 3. USB Controller
+ * 4. Serial Controller
+ *
+ * We configure IRQ5 as a cascade IRQ.
+ */
+static struct irqaction irq5 = { no_action, 0, CPU_MASK_NONE, "IRQ5-cascade",
+                               NULL, NULL};
+
+/*
+ * Initialize IRQ setting
+ */
+void __init
+init_7343se_IRQ(void)
+{
+       /* Setup Multiplexed interrupts */
+       ctrl_outw(8, PA_CPLD_MODESET);  /* Set all CPLD interrupts to active
+                                        * low.
+                                        */
+       /* Mask all CPLD controller interrupts */
+       ctrl_outw(0x0fff, PA_CPLD_IMSK);
+
+       /* PC Card interrupts */
+       make_intreq_irq(PC_IRQ0);
+       make_intreq_irq(PC_IRQ1);
+       make_intreq_irq(PC_IRQ2);
+       make_intreq_irq(PC_IRQ3);
+
+       /* Extension Slot Interrupts */
+       make_intreq_irq(EXT_IRQ0);
+       make_intreq_irq(EXT_IRQ1);
+       make_intreq_irq(EXT_IRQ2);
+       make_intreq_irq(EXT_IRQ3);
+
+       /* USB Controller interrupts */
+       make_intreq_irq(USB_IRQ0);
+       make_intreq_irq(USB_IRQ1);
+
+       /* Serial Controller interrupts */
+       make_intreq_irq(UART_IRQ0);
+       make_intreq_irq(UART_IRQ1);
+
+       /* Setup all external interrupts to be active low */
+       ctrl_outw(0xaaaa, INTC_ICR1);
+
+       make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR+2, IRQ5_IPR_POS, IRQ5_PRIORITY);
+       setup_irq(IRQ5_IRQ, &irq5);
+       /* Set port control to use IRQ5 */
+       *(u16 *)0xA4050108 &= ~0xc;
+
+       make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
+       make_ipr_irq(VPU_IRQ, VPU_IPR_ADDR, VPU_IPR_POS, 8);
+
+       ctrl_outb(0x0f, INTC_IMCR5);    /* enable SCIF IRQ */
+
+       make_ipr_irq(DMTE0_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+       make_ipr_irq(DMTE1_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+       make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+       make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY);
+       make_ipr_irq(DMTE4_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+       make_ipr_irq(DMTE5_IRQ, DMA2_IPR_ADDR, DMA2_IPR_POS, DMA2_PRIORITY);
+
+       /* I2C block */
+       make_ipr_irq(IIC0_ALI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
+       make_ipr_irq(IIC0_TACKI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
+                    IIC0_PRIORITY);
+       make_ipr_irq(IIC0_WAITI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS,
+                    IIC0_PRIORITY);
+       make_ipr_irq(IIC0_DTEI_IRQ, IIC0_IPR_ADDR, IIC0_IPR_POS, IIC0_PRIORITY);
+
+       make_ipr_irq(IIC1_ALI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY);
+       make_ipr_irq(IIC1_TACKI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS,
+                    IIC1_PRIORITY);
+       make_ipr_irq(IIC1_WAITI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS,
+                    IIC1_PRIORITY);
+       make_ipr_irq(IIC1_DTEI_IRQ, IIC1_IPR_ADDR, IIC1_IPR_POS, IIC1_PRIORITY);
+
+       /* SIOF */
+       make_ipr_irq(SIOF0_IRQ, SIOF0_IPR_ADDR, SIOF0_IPR_POS, SIOF0_PRIORITY);
+
+       /* SIU */
+       make_ipr_irq(SIU_IRQ, SIU_IPR_ADDR, SIU_IPR_POS, SIU_PRIORITY);
+
+       /* VIO interrupt */
+       make_ipr_irq(CEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+       make_ipr_irq(BEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+       make_ipr_irq(VEU_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY);
+
+       /*MFI interrupt*/
+
+       make_ipr_irq(MFI_IRQ, MFI_IPR_ADDR, MFI_IPR_POS, MFI_PRIORITY);
+
+       /* LCD controller */
+       make_ipr_irq(LCDC_IRQ, LCDC_IPR_ADDR, LCDC_IPR_POS, LCDC_PRIORITY);
+       ctrl_outw(0x2000, PA_MRSHPC + 0x0c);    /* mrshpc irq enable */
+}
diff --git a/arch/sh/boards/se/7343/led.c b/arch/sh/boards/se/7343/led.c
new file mode 100644 (file)
index 0000000..6a439cf
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * arch/sh/boards/se/7343/led.c
+ *
+ */
+
+#include <linux/config.h>
+#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);
+
+}
diff --git a/arch/sh/boards/se/7343/setup.c b/arch/sh/boards/se/7343/setup.c
new file mode 100644 (file)
index 0000000..7873222
--- /dev/null
@@ -0,0 +1,84 @@
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <asm/machvec.h>
+#include <asm/mach/se7343.h>
+#include <asm/irq.h>
+
+void heartbeat_7343se(void);
+void init_7343se_IRQ(void);
+
+static struct resource smc91x_resources[] = {
+       [0] = {
+               .start  = 0x10000000,
+               .end    = 0x1000000F,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /*
+                * shared with other devices via externel
+                * interrupt controller in FPGA...
+                */
+               .start  = EXT_IRQ2,
+               .end    = EXT_IRQ2,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device smc91x_device = {
+       .name           = "smc91x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smc91x_resources),
+       .resource       = smc91x_resources,
+};
+
+static struct platform_device *smc91x_platform_devices[] __initdata = {
+       &smc91x_device,
+};
+
+static int __init sh7343se_devices_setup(void)
+{
+       return platform_add_devices(smc91x_platform_devices,
+                                   ARRAY_SIZE(smc91x_platform_devices));
+}
+
+static void __init sh7343se_setup(char **cmdline_p)
+{
+       device_initcall(sh7343se_devices_setup);
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_7343se __initmv = {
+       .mv_name = "SolutionEngine 7343",
+       .mv_setup = sh7343se_setup,
+       .mv_nr_irqs = 108,
+       .mv_inb = sh7343se_inb,
+       .mv_inw = sh7343se_inw,
+       .mv_inl = sh7343se_inl,
+       .mv_outb = sh7343se_outb,
+       .mv_outw = sh7343se_outw,
+       .mv_outl = sh7343se_outl,
+
+       .mv_inb_p = sh7343se_inb_p,
+       .mv_inw_p = sh7343se_inw,
+       .mv_inl_p = sh7343se_inl,
+       .mv_outb_p = sh7343se_outb_p,
+       .mv_outw_p = sh7343se_outw,
+       .mv_outl_p = sh7343se_outl,
+
+       .mv_insb = sh7343se_insb,
+       .mv_insw = sh7343se_insw,
+       .mv_insl = sh7343se_insl,
+       .mv_outsb = sh7343se_outsb,
+       .mv_outsw = sh7343se_outsw,
+       .mv_outsl = sh7343se_outsl,
+
+       .mv_init_irq = init_7343se_IRQ,
+       .mv_irq_demux = shmse_irq_demux,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat = heartbeat_7343se,
+#endif
+};
+ALIAS_MV(7343se)
index be89a73cc418aede40d3cbbfd0f2baec468b4352..9a5035f80ec03987aadf37f3e72623a76c6ed179 100644 (file)
@@ -2,5 +2,5 @@
 # Makefile for the 770x SolutionEngine specific parts of the kernel
 #
 
-obj-y   := mach.o setup.o io.o irq.o led.o
-
+obj-y   := setup.o io.o irq.o
+obj-$(CONFIG_HEARTBEAT) += led.o
index 9a39ee963143fa4169bae4e9bb46abaabcf27a68..9941949331abee325bea7f35f97a52b2673a6b01 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: io.c,v 1.5 2004/02/22 23:08:43 kkojima Exp $
+/* $Id: io.c,v 1.7 2006/02/05 21:55:29 lethal Exp $
  *
  * linux/arch/sh/kernel/io_se.c
  *
@@ -11,7 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <asm/io.h>
-#include <asm/se/se.h>
+#include <asm/se.h>
 
 /* SH pcmcia io window base, start and end.  */
 int sh_pcic_io_wbase = 0xb8400000;
@@ -20,11 +20,6 @@ int sh_pcic_io_stop;
 int sh_pcic_io_type;
 int sh_pcic_io_dummy;
 
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
 /* MS7750 requires special versions of in*, out* routines, since
    PC-like io ports are located at upper half byte of 16-bit word which
    can be accessed only with 16-bit wide.  */
@@ -52,10 +47,6 @@ shifted_port(unsigned long port)
                return 1;
 }
 
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
 unsigned char se_inb(unsigned long port)
 {
        if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
@@ -76,7 +67,7 @@ unsigned char se_inb_p(unsigned long port)
                v = (*port2adr(port) >> 8); 
        else
                v = (*port2adr(port))&0xff; 
-       delay();
+       ctrl_delay();
        return v;
 }
 
@@ -86,13 +77,13 @@ unsigned short se_inw(unsigned long port)
            (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
                return *port2adr(port);
        else
-               maybebadio(inw, port);
+               maybebadio(port);
        return 0;
 }
 
 unsigned int se_inl(unsigned long port)
 {
-       maybebadio(inl, port);
+       maybebadio(port);
        return 0;
 }
 
@@ -114,7 +105,7 @@ void se_outb_p(unsigned char value, unsigned long port)
                *(port2adr(port)) = value << 8;
        else
                *(port2adr(port)) = value;
-       delay();
+       ctrl_delay();
 }
 
 void se_outw(unsigned short value, unsigned long port)
@@ -123,12 +114,12 @@ void se_outw(unsigned short value, unsigned long port)
            (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
                *port2adr(port) = value;
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
 void se_outl(unsigned int value, unsigned long port)
 {
-       maybebadio(outl, port);
+       maybebadio(port);
 }
 
 void se_insb(unsigned long port, void *addr, unsigned long count)
@@ -159,7 +150,7 @@ void se_insw(unsigned long port, void *addr, unsigned long count)
 
 void se_insl(unsigned long port, void *addr, unsigned long count)
 {
-       maybebadio(insl, port);
+       maybebadio(port);
 }
 
 void se_outsb(unsigned long port, const void *addr, unsigned long count)
@@ -190,37 +181,5 @@ void se_outsw(unsigned long port, const void *addr, unsigned long count)
 
 void se_outsl(unsigned long port, const void *addr, unsigned long count)
 {
-       maybebadio(outsw, port);
-}
-
-/* Map ISA bus address to the real address. Only for PCMCIA.  */
-
-/* ISA page descriptor.  */
-static __u32 sh_isa_memmap[256];
-
-static int
-sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
-       int idx;
-
-       if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
-               return -1;
-
-       idx = start >> 12;
-       sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
-#if 0
-       printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
-              start, length, offset, idx, sh_isa_memmap[idx]);
-#endif
-       return 0;
-}
-
-unsigned long
-se_isa_port2addr(unsigned long offset)
-{
-       int idx;
-
-       idx = (offset >> 12) & 0xff;
-       offset &= 0xfff;
-       return sh_isa_memmap[idx] + offset;
+       maybebadio(port);
 }
index 3e558716ce100fac939c084ecb8285cf382094a4..cff6700bbafd4f98878e462c9121a3057bd87acf 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/irq.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/se/se.h>
+#include <asm/se.h>
 
 /*
  * Initialize IRQ setting
index 3cddbda025fc28d1cd8b7ee431a49042b30199fd..daf7b1ee786a3f7f1d833cc4a1712cbf5d6ae6e1 100644 (file)
@@ -9,22 +9,8 @@
  * This file contains Solution Engine specific LED code.
  */
 
-#include <asm/se/se.h>
-
-static void mach_led(int position, int value)
-{
-       volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-
-       if (value) {
-               *p |= (1<<8);
-       } else {
-               *p &= ~(1<<8);
-       }
-}
-
-#ifdef CONFIG_HEARTBEAT
-
 #include <linux/sched.h>
+#include <asm/se.h>
 
 /* Cycle the LED's in the clasic Knightrider/Sun pattern */
 void heartbeat_se(void)
@@ -64,4 +50,3 @@ void heartbeat_se(void)
        *p = 1<<(bit+8);
 
 }
-#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/770x/mach.c b/arch/sh/boards/se/770x/mach.c
deleted file mode 100644 (file)
index 6ec07bd..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_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.
- *
- * Machine vector for the Hitachi SolutionEngine
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/se/io.h>
-
-void heartbeat_se(void);
-void setup_se(void);
-void init_se_IRQ(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_se __initmv = {
-#if defined(CONFIG_CPU_SH4)
-       .mv_nr_irqs             = 48,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
-       .mv_nr_irqs             = 32,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
-       .mv_nr_irqs             = 61,
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-       .mv_nr_irqs             = 86,
-#endif
-
-       .mv_inb                 = se_inb,
-       .mv_inw                 = se_inw,
-       .mv_inl                 = se_inl,
-       .mv_outb                = se_outb,
-       .mv_outw                = se_outw,
-       .mv_outl                = se_outl,
-
-       .mv_inb_p               = se_inb_p,
-       .mv_inw_p               = se_inw,
-       .mv_inl_p               = se_inl,
-       .mv_outb_p              = se_outb_p,
-       .mv_outw_p              = se_outw,
-       .mv_outl_p              = se_outl,
-
-       .mv_insb                = se_insb,
-       .mv_insw                = se_insw,
-       .mv_insl                = se_insl,
-       .mv_outsb               = se_outsb,
-       .mv_outsw               = se_outsw,
-       .mv_outsl               = se_outsl,
-
-       .mv_isa_port2addr       = se_isa_port2addr,
-
-       .mv_init_irq            = init_se_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_se,
-#endif
-};
-ALIAS_MV(se)
index 7d1a071727cc57da4ed3bf18c7fc52f4e99c1217..f3f82b7c821740b22849caadb665d82330fdca0c 100644 (file)
@@ -7,15 +7,17 @@
  * Hitachi SolutionEngine Support.
  *
  */
-
 #include <linux/init.h>
 #include <linux/irq.h>
-
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <asm/io.h>
-#include <asm/se/se.h>
-#include <asm/se/smc37c93x.h>
+#include <asm/se.h>
+#include <asm/smc37c93x.h>
+#include <asm/machvec.h>
+
+void heartbeat_se(void);
+void init_se_IRQ(void);
 
 /*
  * Configure the Super I/O chip
@@ -26,7 +28,8 @@ static void __init smsc_config(int index, int data)
        outb_p(data, DATA_PORT);
 }
 
-static void __init init_smsc(void)
+/* XXX: Another candidate for a more generic cchip machine vector */
+static void __init smsc_setup(char **cmdline_p)
 {
        outb_p(CONFIG_ENTER, CONFIG_PORT);
        outb_p(CONFIG_ENTER, CONFIG_PORT);
@@ -69,16 +72,46 @@ static void __init init_smsc(void)
        outb_p(CONFIG_EXIT, CONFIG_PORT);
 }
 
-const char *get_system_type(void)
-{
-       return "SolutionEngine";
-}
-
 /*
- * Initialize the board
+ * The Machine Vector
  */
-void __init platform_setup(void)
-{
-       init_smsc();
-       /* XXX: RTC setting comes here */
-}
+struct sh_machine_vector mv_se __initmv = {
+       .mv_name                = "SolutionEngine",
+       .mv_setup               = smsc_setup,
+#if defined(CONFIG_CPU_SH4)
+       .mv_nr_irqs             = 48,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7708)
+       .mv_nr_irqs             = 32,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7709)
+       .mv_nr_irqs             = 61,
+#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
+       .mv_nr_irqs             = 86,
+#endif
+
+       .mv_inb                 = se_inb,
+       .mv_inw                 = se_inw,
+       .mv_inl                 = se_inl,
+       .mv_outb                = se_outb,
+       .mv_outw                = se_outw,
+       .mv_outl                = se_outl,
+
+       .mv_inb_p               = se_inb_p,
+       .mv_inw_p               = se_inw,
+       .mv_inl_p               = se_inl,
+       .mv_outb_p              = se_outb_p,
+       .mv_outw_p              = se_outw,
+       .mv_outl_p              = se_outl,
+
+       .mv_insb                = se_insb,
+       .mv_insw                = se_insw,
+       .mv_insl                = se_insl,
+       .mv_outsb               = se_outsb,
+       .mv_outsw               = se_outsw,
+       .mv_outsl               = se_outsl,
+
+       .mv_init_irq            = init_se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = heartbeat_se,
+#endif
+};
+ALIAS_MV(se)
index ce7ca247f84d04dfbe722f689655eb39b56e1d72..188900c48321335bca050c9d1b8b161d9fec7c3a 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the 7751 SolutionEngine specific parts of the kernel
 #
 
-obj-y   := mach.o setup.o io.o irq.o led.o
+obj-y   := setup.o io.o irq.o
 
 obj-$(CONFIG_PCI) += pci.o
-
+obj-$(CONFIG_HEARTBEAT) += led.o
index 99041b26926121f33be525e3432daaa656a11f7f..e8d846cec89d1b82c6d323a22e4f0e74c7abea54 100644 (file)
@@ -1,6 +1,4 @@
-/* 
- * linux/arch/sh/kernel/io_7751se.c
- *
+/*
  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
  * Based largely on io_se.c.
  *
  * placeholder code from io_se.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 <asm/io.h>
-#include <asm/se7751/se7751.h>
+#include <asm/se7751.h>
 #include <asm/addrspace.h>
 
-#include <linux/pci.h>
-#include "../../../drivers/pci/pci-sh7751.h"
-
-#if 0
-/******************************************************************
- * Variables from io_se.c, related to PCMCIA (not PCI); we're not
- * compiling them in, and have removed references from functions
- * which follow.  [Many checked for IO ports in the range bounded
- * by sh_pcic_io_start/stop, and used sh_pcic_io_wbase as offset.
- * As start/stop are uninitialized, only port 0x0 would match?]
- * When used, remember to adjust names to avoid clash with io_se?
- *****************************************************************/
-/* SH pcmcia io window base, start and end.  */
-int sh_pcic_io_wbase = 0xb8400000;
-int sh_pcic_io_start;
-int sh_pcic_io_stop;
-int sh_pcic_io_type;
-int sh_pcic_io_dummy;
-/*************************************************************/
-#endif
-
-/*
- * The 7751 Solution Engine uses the built-in PCI controller (PCIC)
- * of the 7751 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.
- */ 
-
-#define PCIIOBR                (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA    SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA   SH7751_PCI_CONFIG_BASE
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
-static inline volatile __u16 *
-port2adr(unsigned int port)
+static inline volatile u16 *port2adr(unsigned int port)
 {
        if (port >= 0x2000)
                return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
-#if 0
-       else
-               return (volatile __u16 *) (PA_SUPERIO + (port << 1));
-#endif
-       maybebadio(name,(unsigned long)port);
+       maybebadio((unsigned long)port);
        return (volatile __u16*)port;
 }
 
-#if 0
-/* The 7751 Solution Engine 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;
-}
-#endif
-
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
-  ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(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)
@@ -111,10 +34,10 @@ unsigned char sh7751se_inb(unsigned long port)
 {
        if (PXSEG(port))
                return *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               return *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               return *(volatile unsigned char *)pci_ioaddr(port);
        else
-               return (*port2adr(port))&0xff; 
+               return (*port2adr(port)) & 0xff;
 }
 
 unsigned char sh7751se_inb_p(unsigned long port)
@@ -123,11 +46,11 @@ unsigned char sh7751se_inb_p(unsigned long port)
 
         if (PXSEG(port))
                 v = *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                v = *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                v = *(volatile unsigned char *)pci_ioaddr(port);
        else
-               v = (*port2adr(port))&0xff; 
-       delay();
+               v = (*port2adr(port)) & 0xff;
+       ctrl_delay();
        return v;
 }
 
@@ -135,12 +58,12 @@ unsigned short sh7751se_inw(unsigned long port)
 {
         if (PXSEG(port))
                 return *(volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                return *(volatile unsigned short *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                return *(volatile unsigned short *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else
-               maybebadio(inw, port);
+               maybebadio(port);
        return 0;
 }
 
@@ -148,12 +71,12 @@ unsigned int sh7751se_inl(unsigned long port)
 {
         if (PXSEG(port))
                 return *(volatile unsigned long *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-                return *(volatile unsigned int *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+                return *(volatile unsigned int *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else
-               maybebadio(inl, port);
+               maybebadio(port);
        return 0;
 }
 
@@ -162,8 +85,8 @@ void sh7751se_outb(unsigned char value, unsigned long port)
 
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else
                *(port2adr(port)) = value;
 }
@@ -172,73 +95,41 @@ void sh7751se_outb_p(unsigned char value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else
                *(port2adr(port)) = value;
-       delay();
+       ctrl_delay();
 }
 
 void sh7751se_outw(unsigned short value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned short *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned short *)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned short *)pci_ioaddr(port)) = value;
        else if (port >= 0x2000)
                *port2adr(port) = value;
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
 void sh7751se_outl(unsigned int value, unsigned long port)
 {
         if (PXSEG(port))
                 *(volatile unsigned long *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned long*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned long*)pci_ioaddr(port)) = value;
        else
-               maybebadio(outl, port);
+               maybebadio(port);
 }
 
 void sh7751se_insl(unsigned long port, void *addr, unsigned long count)
 {
-       maybebadio(insl, port);
+       maybebadio(port);
 }
 
 void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count)
 {
-       maybebadio(outsw, port);
-}
-
-/* Map ISA bus address to the real address. Only for PCMCIA.  */
-
-/* ISA page descriptor.  */
-static __u32 sh_isa_memmap[256];
-
-#if 0
-static int
-sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
-       int idx;
-
-       if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
-               return -1;
-
-       idx = start >> 12;
-       sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
-       printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
-              start, length, offset, idx, sh_isa_memmap[idx]);
-       return 0;
-}
-#endif
-
-unsigned long
-sh7751se_isa_port2addr(unsigned long offset)
-{
-       int idx;
-
-       idx = (offset >> 12) & 0xff;
-       offset &= 0xfff;
-       return sh_isa_memmap[idx] + offset;
+       maybebadio(port);
 }
index bf6c023615df87306125654263eca40d0421ff7e..c607b0a48479d87b14ebff2d81263f8ae650cca1 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <asm/irq.h>
-#include <asm/se7751/se7751.h>
+#include <asm/se7751.h>
 
 /*
  * Initialize IRQ setting
index a878726d3c7c8d5019be1d96bbc94cb0d496a20c..ff0355dea81b37ba235c0c53953917a44cb1a786 100644 (file)
@@ -8,23 +8,8 @@
  *
  * This file contains Solution Engine specific LED code.
  */
-
-#include <asm/se7751/se7751.h>
-
-static void mach_led(int position, int value)
-{
-       volatile unsigned short* p = (volatile unsigned short*)PA_LED;
-
-       if (value) {
-               *p |= (1<<8);
-       } else {
-               *p &= ~(1<<8);
-       }
-}
-
-#ifdef CONFIG_HEARTBEAT
-
 #include <linux/sched.h>
+#include <asm/se7751.h>
 
 /* Cycle the LED's in the clasic Knightrider/Sun pattern */
 void heartbeat_7751se(void)
@@ -64,4 +49,3 @@ void heartbeat_7751se(void)
        *p = 1<<(bit+8);
 
 }
-#endif /* CONFIG_HEARTBEAT */
diff --git a/arch/sh/boards/se/7751/mach.c b/arch/sh/boards/se/7751/mach.c
deleted file mode 100644 (file)
index 62d8d3e..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * linux/arch/sh/kernel/mach_7751se.c
- *
- * Minor tweak of mach_se.c file to reference 7751se-specific items.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * Machine vector for the Hitachi 7751 SolutionEngine
- */
-
-#include <linux/init.h>
-
-#include <asm/machvec.h>
-#include <asm/rtc.h>
-#include <asm/machvec_init.h>
-
-#include <asm/se7751/io.h>
-
-void heartbeat_7751se(void);
-void init_7751se_IRQ(void);
-
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_7751se __initmv = {
-       .mv_nr_irqs             = 72,
-
-       .mv_inb                 = sh7751se_inb,
-       .mv_inw                 = sh7751se_inw,
-       .mv_inl                 = sh7751se_inl,
-       .mv_outb                = sh7751se_outb,
-       .mv_outw                = sh7751se_outw,
-       .mv_outl                = sh7751se_outl,
-
-       .mv_inb_p               = sh7751se_inb_p,
-       .mv_inw_p               = sh7751se_inw,
-       .mv_inl_p               = sh7751se_inl,
-       .mv_outb_p              = sh7751se_outb_p,
-       .mv_outw_p              = sh7751se_outw,
-       .mv_outl_p              = sh7751se_outl,
-
-       .mv_insl                = sh7751se_insl,
-       .mv_outsl               = sh7751se_outsl,
-
-       .mv_isa_port2addr       = sh7751se_isa_port2addr,
-
-       .mv_init_irq            = init_7751se_IRQ,
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = heartbeat_7751se,
-#endif
-};
-ALIAS_MV(7751se)
index 48dc5aee67d4d6c6cd4edc3225cd3749cfe29af3..73e826310ba8748379395871c663681cbfa99939 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * linux/arch/sh/kernel/setup_7751se.c
  *
  * Copyright (C) 2000  Kazumoto Kojima
 
 #include <linux/init.h>
 #include <linux/irq.h>
-
-#include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <asm/io.h>
-#include <asm/se7751/se7751.h>
+#include <asm/se7751.h>
 
-#ifdef CONFIG_SH_KGDB
-#include <asm/kgdb.h>
-#endif
-
-/*
- * Configure the Super I/O chip
- */
-#if 0
-/* Leftover code from regular Solution Engine, for reference. */
-/* The SH7751 Solution Engine has a different SuperIO. */
-static void __init smsc_config(int index, int data)
-{
-       outb_p(index, INDEX_PORT);
-       outb_p(data, DATA_PORT);
-}
-
-static void __init init_smsc(void)
-{
-       outb_p(CONFIG_ENTER, CONFIG_PORT);
-       outb_p(CONFIG_ENTER, CONFIG_PORT);
-
-       /* FDC */
-       smsc_config(CURRENT_LDN_INDEX, LDN_FDC);
-       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 */
-       smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */
-
-       /* COM1 */
-       smsc_config(CURRENT_LDN_INDEX, LDN_COM1);
-       smsc_config(ACTIVATE_INDEX, 0x01);
-       smsc_config(IO_BASE_HI_INDEX, 0x03);
-       smsc_config(IO_BASE_LO_INDEX, 0xf8);
-       smsc_config(IRQ_SELECT_INDEX, 4); /* IRQ4 */
-
-       /* COM2 */
-       smsc_config(CURRENT_LDN_INDEX, LDN_COM2);
-       smsc_config(ACTIVATE_INDEX, 0x01);
-       smsc_config(IO_BASE_HI_INDEX, 0x02);
-       smsc_config(IO_BASE_LO_INDEX, 0xf8);
-       smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */
-
-       /* RTC */
-       smsc_config(CURRENT_LDN_INDEX, LDN_RTC);
-       smsc_config(ACTIVATE_INDEX, 0x01);
-       smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */
-
-       /* XXX: PARPORT, KBD, and MOUSE will come here... */
-       outb_p(CONFIG_EXIT, CONFIG_PORT);
-}
-#endif
-
-const char *get_system_type(void)
-{
-       return "7751 SolutionEngine";
-}
+void heartbeat_7751se(void);
+void init_7751se_IRQ(void);
 
 #ifdef CONFIG_SH_KGDB
+#include <asm/kgdb.h>
 static int kgdb_uart_setup(void);
 static struct kgdb_sermap kgdb_uart_sermap = 
 { "ttyS", 0, kgdb_uart_setup, NULL };
@@ -91,7 +28,7 @@ static struct kgdb_sermap kgdb_uart_sermap =
 /*
  * Initialize the board
  */
-void __init platform_setup(void)
+static void __init sh7751se_setup(char **cmdline_p)
 {
        /* Call init_smsc() replacement to set up SuperIO. */
        /* XXX: RTC setting comes here */
@@ -225,3 +162,37 @@ static int kgdb_uart_setup(void)
        return 0;
 }
 #endif /* CONFIG_SH_KGDB */
+
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_7751se __initmv = {
+       .mv_name                = "7751 SolutionEngine",
+       .mv_setup               = sh7751se_setup,
+       .mv_nr_irqs             = 72,
+
+       .mv_inb                 = sh7751se_inb,
+       .mv_inw                 = sh7751se_inw,
+       .mv_inl                 = sh7751se_inl,
+       .mv_outb                = sh7751se_outb,
+       .mv_outw                = sh7751se_outw,
+       .mv_outl                = sh7751se_outl,
+
+       .mv_inb_p               = sh7751se_inb_p,
+       .mv_inw_p               = sh7751se_inw,
+       .mv_inl_p               = sh7751se_inl,
+       .mv_outb_p              = sh7751se_outb_p,
+       .mv_outw_p              = sh7751se_outw,
+       .mv_outl_p              = sh7751se_outl,
+
+       .mv_insl                = sh7751se_insl,
+       .mv_outsl               = sh7751se_outsl,
+
+       .mv_init_irq            = init_7751se_IRQ,
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = heartbeat_7751se,
+#endif
+};
+ALIAS_MV(7751se)
index d609863cfe53fba5ba3068da2d1d78a95d2bade5..0a9266bb51c58bcd7309dcf15b5870b563a08f11 100644 (file)
 #include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/bcd.h>
-#include <asm/io.h>
 #include <linux/rtc.h>
 #include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/rtc.h>
 
 #define RTC_BASE       0xb0000000
 #define RTC_SEC1       (RTC_BASE + 0)
@@ -34,8 +35,6 @@
 #define RTC_BUSY       1
 #define RTC_STOP       2
 
-extern void (*rtc_get_time)(struct timespec *);
-extern int (*rtc_set_time)(const time_t);
 extern spinlock_t rtc_lock;
 
 unsigned long get_cmos_time(void)
@@ -128,6 +127,6 @@ int sh03_rtc_settimeofday(const time_t secs)
 
 void sh03_time_init(void)
 {
-       rtc_get_time = sh03_rtc_gettimeofday;
-       rtc_set_time = sh03_rtc_settimeofday;
+       rtc_sh_get_time = sh03_rtc_gettimeofday;
+       rtc_sh_set_time = sh03_rtc_settimeofday;
 }
index 60290f8f289c49fda70b3f6ee6912b6f6b63ea8a..6c310587ddfe72ecc15848d34297e1e52ec7f2b0 100644 (file)
@@ -7,22 +7,13 @@
 
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
 #include <asm/io.h>
+#include <asm/rtc.h>
 #include <asm/sh03/io.h>
 #include <asm/sh03/sh03.h>
 #include <asm/addrspace.h>
-#include "../../drivers/pci/pci-sh7751.h"
 
-extern void (*board_time_init)(void);
-
-const char *get_system_type(void)
-{
-       return "Interface CTP/PCI-SH03)";
-}
-
-void init_sh03_IRQ(void)
+static void __init init_sh03_IRQ(void)
 {
        ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
 
@@ -34,38 +25,34 @@ void init_sh03_IRQ(void)
 
 extern void *cf_io_base;
 
-unsigned long sh03_isa_port2addr(unsigned long port)
+static void __iomem *sh03_ioport_map(unsigned long port, unsigned int size)
 {
        if (PXSEG(port))
-               return port;
+               return (void __iomem *)port;
        /* CompactFlash (IDE) */
-       if (((port >= 0x1f0) && (port <= 0x1f7)) || (port == 0x3f6)) {
-               return (unsigned long)cf_io_base + port;
-       }
-        return port + SH7751_PCI_IO_BASE;
+       if (((port >= 0x1f0) && (port <= 0x1f7)) || (port == 0x3f6))
+               return (void __iomem *)((unsigned long)cf_io_base + port);
+
+        return (void __iomem *)(port + PCI_IO_BASE);
 }
 
-/*
- * The Machine Vector
- */
+/* arch/sh/boards/sh03/rtc.c */
+void sh03_time_init(void);
+
+static void __init sh03_setup(char **cmdline_p)
+{
+       board_time_init = sh03_time_init;
+}
 
 struct sh_machine_vector mv_sh03 __initmv = {
+       .mv_name                = "Interface (CTP/PCI-SH03)",
+       .mv_setup               = sh03_setup,
        .mv_nr_irqs             = 48,
-       .mv_isa_port2addr       = sh03_isa_port2addr,
+       .mv_ioport_map          = sh03_ioport_map,
        .mv_init_irq            = init_sh03_IRQ,
 
 #ifdef CONFIG_HEARTBEAT
        .mv_heartbeat           = heartbeat_sh03,
 #endif
 };
-
 ALIAS_MV(sh03)
-
-/* arch/sh/boards/sh03/rtc.c */
-void sh03_time_init(void);
-
-int __init platform_setup(void)
-{
-       board_time_init = sh03_time_init;
-       return 0;
-}
diff --git a/arch/sh/boards/sh2000/Makefile b/arch/sh/boards/sh2000/Makefile
deleted file mode 100644 (file)
index 05d390c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for the SH2000 specific parts of the kernel
-#
-
-obj-y   := setup.o
-
diff --git a/arch/sh/boards/sh2000/setup.c b/arch/sh/boards/sh2000/setup.c
deleted file mode 100644 (file)
index 2fe6a11..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * linux/arch/sh/kernel/setup_sh2000.c
- *
- * Copyright (C) 2001  SUGIOKA Tochinobu
- *
- * SH-2000 Support.
- *
- */
-
-#include <linux/init.h>
-#include <linux/irq.h>
-
-#include <asm/io.h>
-#include <asm/machvec.h>
-#include <asm/mach/sh2000.h>
-
-#define CF_CIS_BASE    0xb4200000
-
-#define PORT_PECR      0xa4000108
-#define PORT_PHCR      0xa400010E
-#define        PORT_ICR1       0xa4000010
-#define        PORT_IRR0       0xa4000004
-
-#define IDE_OFFSET     0xb6200000
-#define NIC_OFFSET     0xb6000000
-#define EXTBUS_OFFSET  0xba000000
-
-
-const char *get_system_type(void)
-{
-       return "sh2000";
-}
-
-static unsigned long sh2000_isa_port2addr(unsigned long offset)
-{
-       if((offset & ~7) == 0x1f0 || offset == 0x3f6)
-               return IDE_OFFSET + offset;
-       else if((offset & ~0x1f) == 0x300)
-               return NIC_OFFSET + offset;
-       return EXTBUS_OFFSET + offset;
-}
-
-/*
- * The Machine Vector
- */
-struct sh_machine_vector mv_sh2000 __initmv = {
-        .mv_nr_irqs            = 80,
-        .mv_isa_port2addr      = sh2000_isa_port2addr,
-};
-ALIAS_MV(sh2000)
-
-/*
- * Initialize the board
- */
-int __init platform_setup(void)
-{
-       /* XXX: RTC setting comes here */
-
-       /* These should be done by BIOS/IPL ... */
-       /* Enable nCE2A, nCE2B output */
-       ctrl_outw(ctrl_inw(PORT_PECR) & ~0xf00, PORT_PECR);
-       /* Enable the Compact Flash card, and set the level interrupt */
-       ctrl_outw(0x0042, CF_CIS_BASE+0x0200);
-       /* Enable interrupt */
-       ctrl_outw(ctrl_inw(PORT_PHCR) & ~0x03f3, PORT_PHCR);
-       ctrl_outw(1, PORT_ICR1);
-       ctrl_outw(ctrl_inw(PORT_IRR0) & ~0xff3f, PORT_IRR0);
-       printk(KERN_INFO "SH-2000 Setup...done\n");
-       return 0;
-}
diff --git a/arch/sh/boards/shmin/Makefile b/arch/sh/boards/shmin/Makefile
new file mode 100644 (file)
index 0000000..3190cc7
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the SHMIN board.
+#
+
+obj-y   := setup.o
diff --git a/arch/sh/boards/shmin/setup.c b/arch/sh/boards/shmin/setup.c
new file mode 100644 (file)
index 0000000..2f0c197
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * arch/sh/boards/shmin/setup.c
+ *
+ * Copyright (C) 2006 Takashi YOSHII
+ *
+ * SHMIN Support.
+ */
+#include <linux/init.h>
+#include <asm/machvec.h>
+#include <asm/shmin/shmin.h>
+#include <asm/clock.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#define PFC_PHCR       0xa400010e
+
+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.
+}
+
+static void __iomem *shmin_ioport_map(unsigned long port, unsigned int size)
+{
+       static int dummy;
+
+       if ((port & ~0x1f) == SHMIN_NE_BASE)
+               return (void __iomem *)(SHMIN_IO_BASE + port);
+
+       dummy = 0;
+
+       return &dummy;
+
+}
+
+struct sh_machine_vector mv_shmin __initmv = {
+       .mv_name        = "SHMIN",
+       .mv_init_irq    = init_shmin_irq,
+       .mv_ioport_map  = shmin_ioport_map,
+};
+ALIAS_MV(shmin)
index e2eb78fc381d6573b072cadcbc6e5fbdb7bacd7c..0f4824264557deae48a2b6719a475ea3f0b21175 100644 (file)
@@ -1,6 +1,4 @@
-/* 
- * linux/arch/sh/kernel/io_7751se.c
- *
+/*
  * Copyright (C) 2002  David McCullough <davidm@snapgear.com>
  * Copyright (C) 2001  Ian da Silva, Jeremy Siegel
  * Based largely on io_se.c.
  * placeholder code from io_se.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 <asm/io.h>
 #include <asm/addrspace.h>
 
-#include <asm/pci.h>
-#include "../../drivers/pci/pci-sh7751.h"
-
 #ifdef CONFIG_SH_SECUREEDGE5410
 unsigned short secureedge5410_ioport;
 #endif
 
-/*
- * The SnapGear uses the built-in PCI controller (PCIC)
- * of the 7751 processor
- */ 
-
-#define PCIIOBR                (volatile long *)PCI_REG(SH7751_PCIIOBR)
-#define PCIMBR          (volatile long *)PCI_REG(SH7751_PCIMBR)
-#define PCI_IO_AREA    SH7751_PCI_IO_BASE
-#define PCI_MEM_AREA   SH7751_PCI_CONFIG_BASE
-
-
-#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK))
-
-
-#define maybebadio(name,port) \
-  printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \
-        #name, (port), (__u32) __builtin_return_address(0))
-
-
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
-
 static inline volatile __u16 *port2adr(unsigned int port)
 {
-#if 0
-       if (port >= 0x2000)
-               return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
-#endif
-       maybebadio(name,(unsigned long)port);
+       maybebadio((unsigned long)port);
        return (volatile __u16*)port;
 }
 
-
-/* In case someone configures the kernel w/o PCI support: in that */
-/* scenario, don't ever bother to check for PCI-window addresses */
-
-/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */
-#if defined(CONFIG_PCI)
-#define CHECK_SH7751_PCIIO(port) \
-  ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
-#else
-#define CHECK_SH7751_PCIIO(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)
@@ -79,148 +32,106 @@ static inline volatile __u16 *port2adr(unsigned int port)
  * should be way beyond the window, and is used  w/o translation for
  * compatibility.
  */
-
 unsigned char snapgear_inb(unsigned long port)
 {
        if (PXSEG(port))
                return *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               return *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               return *(volatile unsigned char *)pci_ioaddr(port);
        else
-               return (*port2adr(port))&0xff; 
+               return (*port2adr(port)) & 0xff;
 }
 
-
 unsigned char snapgear_inb_p(unsigned long port)
 {
        unsigned char v;
 
        if (PXSEG(port))
                v = *(volatile unsigned char *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               v = *(volatile unsigned char *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               v = *(volatile unsigned char *)pci_ioaddr(port);
        else
-               v = (*port2adr(port))&0xff; 
-       delay();
+               v = (*port2adr(port))&0xff;
+       ctrl_delay();
        return v;
 }
 
-
 unsigned short snapgear_inw(unsigned long port)
 {
        if (PXSEG(port))
                return *(volatile unsigned short *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               return *(volatile unsigned short *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               return *(volatile unsigned short *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else
-               maybebadio(inw, port);
+               maybebadio(port);
        return 0;
 }
 
-
 unsigned int snapgear_inl(unsigned long port)
 {
        if (PXSEG(port))
                return *(volatile unsigned long *)port;
-       else if (CHECK_SH7751_PCIIO(port))
-               return *(volatile unsigned int *)PCI_IOMAP(port);
+       else if (is_pci_ioaddr(port))
+               return *(volatile unsigned int *)pci_ioaddr(port);
        else if (port >= 0x2000)
                return *port2adr(port);
        else
-               maybebadio(inl, port);
+               maybebadio(port);
        return 0;
 }
 
-
 void snapgear_outb(unsigned char value, unsigned long port)
 {
 
        if (PXSEG(port))
                *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else
                *(port2adr(port)) = value;
 }
 
-
 void snapgear_outb_p(unsigned char value, unsigned long port)
 {
        if (PXSEG(port))
                *(volatile unsigned char *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned char*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned char*)pci_ioaddr(port)) = value;
        else
                *(port2adr(port)) = value;
-       delay();
+       ctrl_delay();
 }
 
-
 void snapgear_outw(unsigned short value, unsigned long port)
 {
        if (PXSEG(port))
                *(volatile unsigned short *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned short *)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned short *)pci_ioaddr(port)) = value;
        else if (port >= 0x2000)
                *port2adr(port) = value;
        else
-               maybebadio(outw, port);
+               maybebadio(port);
 }
 
-
 void snapgear_outl(unsigned int value, unsigned long port)
 {
        if (PXSEG(port))
                *(volatile unsigned long *)port = value;
-       else if (CHECK_SH7751_PCIIO(port))
-               *((unsigned long*)PCI_IOMAP(port)) = value;
+       else if (is_pci_ioaddr(port))
+               *((unsigned long*)pci_ioaddr(port)) = value;
        else
-               maybebadio(outl, port);
+               maybebadio(port);
 }
 
 void snapgear_insl(unsigned long port, void *addr, unsigned long count)
 {
-       maybebadio(insl, port);
+       maybebadio(port);
 }
 
 void snapgear_outsl(unsigned long port, const void *addr, unsigned long count)
 {
-       maybebadio(outsw, port);
-}
-
-/* Map ISA bus address to the real address. Only for PCMCIA.  */
-
-
-/* ISA page descriptor.  */
-static __u32 sh_isa_memmap[256];
-
-
-#if 0
-static int sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
-{
-       int idx;
-
-       if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
-               return -1;
-
-       idx = start >> 12;
-       sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
-#if 0
-       printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
-              start, length, offset, idx, sh_isa_memmap[idx]);
-#endif
-       return 0;
-}
-#endif
-
-unsigned long snapgear_isa_port2addr(unsigned long offset)
-{
-       int idx;
-
-       idx = (offset >> 12) & 0xff;
-       offset &= 0xfff;
-       return sh_isa_memmap[idx] + offset;
+       maybebadio(port);
 }
index b71e009da35cb265dfbcb208527451bff2dbc69f..1659fdd6695a14fcf3ac687016f2bd1a6a3db3b7 100644 (file)
 #include <linux/time.h>
 #include <linux/rtc.h>
 #include <linux/mc146818rtc.h>
-
 #include <asm/io.h>
-#include <asm/rtc.h>
-#include <asm/mc146818rtc.h>
-
-/****************************************************************************/
 
-static int use_ds1302 = 0;
+static int use_ds1302;
 
 /****************************************************************************/
 /*
@@ -82,10 +77,6 @@ static unsigned int ds1302_readbyte(unsigned int addr)
        unsigned int    val;
        unsigned long   flags;
 
-#if 0
-       printk("SnapGear RTC: ds1302_readbyte(addr=%x)\n", addr);
-#endif
-
        local_irq_save(flags);
        set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
        set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
@@ -104,10 +95,6 @@ static void ds1302_writebyte(unsigned int addr, unsigned int val)
 {
        unsigned long   flags;
 
-#if 0
-       printk("SnapGear RTC: ds1302_writebyte(addr=%x)\n", addr);
-#endif
-
        local_irq_save(flags);
        set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK);
        set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK));
@@ -168,11 +155,8 @@ void __init secureedge5410_rtc_init(void)
                }
 
        if (use_ds1302) {
-               rtc_get_time = snapgear_rtc_gettimeofday;
-               rtc_set_time = snapgear_rtc_settimeofday;
-       } else {
-               rtc_get_time = sh_rtc_gettimeofday;
-               rtc_set_time = sh_rtc_settimeofday;
+               rtc_sh_get_time = snapgear_rtc_gettimeofday;
+               rtc_sh_set_time = snapgear_rtc_settimeofday;
        }
                
        printk("SnapGear RTC: using %s rtc.\n", use_ds1302 ? "ds1302" : "internal");
@@ -187,10 +171,8 @@ void snapgear_rtc_gettimeofday(struct timespec *ts)
 {
        unsigned int sec, min, hr, day, mon, yr;
 
-       if (!use_ds1302) {
-               sh_rtc_gettimeofday(ts);
+       if (!use_ds1302)
                return;
-       }
 
        sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC));
        min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN));
@@ -231,7 +213,7 @@ int snapgear_rtc_settimeofday(const time_t secs)
        unsigned long nowtime;
 
        if (!use_ds1302)
-               return sh_rtc_settimeofday(secs);
+               return 0;
 
 /*
  *     This is called direct from the kernel timer handling code.
@@ -240,10 +222,6 @@ int snapgear_rtc_settimeofday(const time_t secs)
 
        nowtime = secs;
 
-#if 1
-       printk("SnapGear RTC: snapgear_rtc_settimeofday(nowtime=%ld)\n", nowtime);
-#endif
-
        /* STOP RTC */
        ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
 
@@ -329,5 +307,3 @@ void secureedge5410_cmos_write(unsigned char val, int addr)
        default:                                                      break;
        }
 }
-
-/****************************************************************************/
index f1f7c70c9402d61384776b0c3ba7927729771d45..f5e98c56b530a7c23d3e43b77e2b063cf19a448f 100644 (file)
@@ -1,5 +1,4 @@
-/****************************************************************************/
-/* 
+/*
  * linux/arch/sh/boards/snapgear/setup.c
  *
  * Copyright (C) 2002  David McCullough <davidm@snapgear.com>
@@ -12,8 +11,6 @@
  *           Modified for 7751 Solution Engine by
  *           Ian da Silva and Jeremy Siegel, 2001.
  */
-/****************************************************************************/
-
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/sched.h>
-
 #include <asm/machvec.h>
-#include <asm/mach/io.h>
+#include <asm/snapgear.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/rtc.h>
 #include <asm/cpu/timer.h>
 
-extern void (*board_time_init)(void);
 extern void secureedge5410_rtc_init(void);
 extern void pcibios_init(void);
 
@@ -85,101 +81,20 @@ static void __init init_snapgear_IRQ(void)
        make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY);
 }
 
-/****************************************************************************/
-/*
- *     Fast poll interrupt simulator.
- */
-
 /*
- * Leave all of the fast timer/fast poll stuff commented out for now, since
- * it's not clear whether it actually works or not. Since it wasn't being used
- * at all in 2.4, we'll assume it's not sane for 2.6 either.. -- PFM
- */
-#if 0
-#define FAST_POLL      1000
-//#define FAST_POLL_INTR
-
-#define FASTTIMER_IRQ   17
-#define FASTTIMER_IPR_ADDR  INTC_IPRA
-#define FASTTIMER_IPR_POS    2
-#define FASTTIMER_PRIORITY   3
-
-#ifdef FAST_POLL_INTR
-#define TMU1_TCR_INIT  0x0020
-#else
-#define TMU1_TCR_INIT  0
-#endif
-#define TMU_TSTR_INIT  1
-#define TMU1_TCR_CALIB 0x0000
-
-
-#ifdef FAST_POLL_INTR
-static void fast_timer_irq(int irq, void *dev_instance, struct pt_regs *regs)
-{
-       unsigned long timer_status;
-    timer_status = ctrl_inw(TMU1_TCR);
-       timer_status &= ~0x100;
-       ctrl_outw(timer_status, TMU1_TCR);
-}
-#endif
-
-/*
- * return the current ticks on the fast timer
- */
-
-unsigned long fast_timer_count(void)
-{
-       return(ctrl_inl(TMU1_TCNT));
-}
-
-/*
- * setup a fast timer for profiling etc etc
+ * Initialize the board
  */
-
-static void setup_fast_timer()
-{
-       unsigned long interval;
-
-#ifdef FAST_POLL_INTR
-       interval = (current_cpu_data.module_clock/4 + FAST_POLL/2) / FAST_POLL;
-
-       make_ipr_irq(FASTTIMER_IRQ, FASTTIMER_IPR_ADDR, FASTTIMER_IPR_POS,
-                       FASTTIMER_PRIORITY);
-
-       printk("SnapGear: %dHz fast timer on IRQ %d\n",FAST_POLL,FASTTIMER_IRQ);
-
-       if (request_irq(FASTTIMER_IRQ, fast_timer_irq, 0, "SnapGear fast timer",
-                       NULL) != 0)
-               printk("%s(%d): request_irq() failed?\n", __FILE__, __LINE__);
-#else
-       printk("SnapGear: fast timer running\n",FAST_POLL,FASTTIMER_IRQ);
-       interval = 0xffffffff;
-#endif
-
-       ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x2, TMU_TSTR); /* disable timer 1 */
-       ctrl_outw(TMU1_TCR_INIT, TMU1_TCR);
-       ctrl_outl(interval, TMU1_TCOR);
-       ctrl_outl(interval, TMU1_TCNT);
-       ctrl_outb(ctrl_inb(TMU_TSTR) | 0x2, TMU_TSTR); /* enable timer 1 */
-
-       printk("Timer count 1 = 0x%x\n", fast_timer_count());
-       udelay(1000);
-       printk("Timer count 2 = 0x%x\n", fast_timer_count());
-}
-#endif
-
-/****************************************************************************/
-
-const char *get_system_type(void)
+static void __init snapgear_setup(char **cmdline_p)
 {
-       return "SnapGear SecureEdge5410";
+       board_time_init = secureedge5410_rtc_init;
 }
 
 /*
  * The Machine Vector
  */
-
 struct sh_machine_vector mv_snapgear __initmv = {
+       .mv_name                = "SnapGear SecureEdge5410",
+       .mv_setup               = snapgear_setup,
        .mv_nr_irqs             = 72,
 
        .mv_inb                 = snapgear_inb,
@@ -196,20 +111,6 @@ struct sh_machine_vector mv_snapgear __initmv = {
        .mv_outw_p              = snapgear_outw,
        .mv_outl_p              = snapgear_outl,
 
-       .mv_isa_port2addr       = snapgear_isa_port2addr,
-
        .mv_init_irq            = init_snapgear_IRQ,
 };
 ALIAS_MV(snapgear)
-
-/*
- * Initialize the board
- */
-
-int __init platform_setup(void)
-{
-       board_time_init = secureedge5410_rtc_init;
-
-       return 0;
-}
-
index 236398fbc0834c00f94021bc7738f8dbacd27b30..8c64baa30364719da119296f487daeb9d8298426 100644 (file)
 
 #include <linux/init.h>
 #include <linux/irq.h>
-
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/microdev.h>
 
 #define NUM_EXTERNAL_IRQS 16   /* IRL0 .. IRL15 */
 
-
 static const struct {
        unsigned char fpgaIrq;
        unsigned char mapped;
@@ -93,53 +91,42 @@ static struct hw_interrupt_type microdev_irq_type = {
 
 static void disable_microdev_irq(unsigned int irq)
 {
-       unsigned int flags;
        unsigned int fpgaIrq;
 
-       if (irq >= NUM_EXTERNAL_IRQS) return;
-       if (!fpgaIrqTable[irq].mapped) return;
+       if (irq >= NUM_EXTERNAL_IRQS)
+               return;
+       if (!fpgaIrqTable[irq].mapped)
+               return;
 
        fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
 
-               /* disable interrupts */
-       local_irq_save(flags);
-
-               /* disable interupts on the FPGA INTC register */
+       /* disable interupts on the FPGA INTC register */
        ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTDSB_REG);
-
-               /* restore interrupts */
-       local_irq_restore(flags);
 }
 
 static void enable_microdev_irq(unsigned int irq)
 {
        unsigned long priorityReg, priorities, pri;
-       unsigned int flags;
        unsigned int fpgaIrq;
 
-
-       if (irq >= NUM_EXTERNAL_IRQS) return;
-       if (!fpgaIrqTable[irq].mapped) return;
+       if (unlikely(irq >= NUM_EXTERNAL_IRQS))
+               return;
+       if (unlikely(!fpgaIrqTable[irq].mapped))
+               return;
 
        pri = 15 - irq;
 
        fpgaIrq = fpgaIrqTable[irq].fpgaIrq;
        priorityReg = MICRODEV_FPGA_INTPRI_REG(fpgaIrq);
 
-               /* disable interrupts */
-       local_irq_save(flags);
-
-               /* set priority for the interrupt */
+       /* set priority for the interrupt */
        priorities = ctrl_inl(priorityReg);
        priorities &= ~MICRODEV_FPGA_INTPRI_MASK(fpgaIrq);
        priorities |= MICRODEV_FPGA_INTPRI_LEVEL(fpgaIrq, pri);
        ctrl_outl(priorities, priorityReg);
 
-               /* enable interupts on the FPGA INTC register */
+       /* enable interupts on the FPGA INTC register */
        ctrl_outl(MICRODEV_FPGA_INTC_MASK(fpgaIrq), MICRODEV_FPGA_INTENB_REG);
-
-               /* restore interrupts */
-       local_irq_restore(flags);
 }
 
        /* This functions sets the desired irq handler to be a MicroDev type */
@@ -158,9 +145,7 @@ static void mask_and_ack_microdev(unsigned int irq)
 static void end_microdev_irq(unsigned int irq)
 {
        if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-       {
                enable_microdev_irq(irq);
-       }
 }
 
 extern void __init init_microdev_irq(void)
@@ -171,9 +156,7 @@ extern void __init init_microdev_irq(void)
        ctrl_outl(~0ul, MICRODEV_FPGA_INTDSB_REG);
 
        for (i = 0; i < NUM_EXTERNAL_IRQS; i++)
-       {
                make_microdev_irq(i);
-       }
 }
 
 extern void microdev_print_fpga_intc_status(void)
index 61b402a3f5d734ac689ea9ac7f68f7bfb2fafc2e..031c814e6e76317aaca6cefb5c4362efa6965cac 100644 (file)
@@ -10,7 +10,6 @@
  * May be copied or modified under the terms of the GNU General Public
  * License.  See linux/COPYING for more information.
  */
-
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/ioport.h>
 
 extern void microdev_heartbeat(void);
 
-/*
- * The Machine Vector
- */
-
-struct sh_machine_vector mv_sh4202_microdev __initmv = {
-       .mv_nr_irqs             = 72,           /* QQQ need to check this - use the MACRO */
-
-       .mv_inb                 = microdev_inb,
-       .mv_inw                 = microdev_inw,
-       .mv_inl                 = microdev_inl,
-       .mv_outb                = microdev_outb,
-       .mv_outw                = microdev_outw,
-       .mv_outl                = microdev_outl,
-
-       .mv_inb_p               = microdev_inb_p,
-       .mv_inw_p               = microdev_inw_p,
-       .mv_inl_p               = microdev_inl_p,
-       .mv_outb_p              = microdev_outb_p,
-       .mv_outw_p              = microdev_outw_p,
-       .mv_outl_p              = microdev_outl_p,
-
-       .mv_insb                = microdev_insb,
-       .mv_insw                = microdev_insw,
-       .mv_insl                = microdev_insl,
-       .mv_outsb               = microdev_outsb,
-       .mv_outsw               = microdev_outsw,
-       .mv_outsl               = microdev_outsl,
-
-       .mv_init_irq            = init_microdev_irq,
-
-#ifdef CONFIG_HEARTBEAT
-       .mv_heartbeat           = microdev_heartbeat,
-#endif
-};
-ALIAS_MV(sh4202_microdev)
 
 /****************************************************************************/
 
@@ -113,11 +77,6 @@ ALIAS_MV(sh4202_microdev)
        /* assume a Keyboard Controller is present */
 int microdev_kbd_controller_present = 1;
 
-const char *get_system_type(void)
-{
-       return "SH4-202 MicroDev";
-}
-
 static struct resource smc91x_resources[] = {
        [0] = {
                .start          = 0x300,
@@ -291,25 +250,9 @@ static int __init microdev_devices_setup(void)
        return platform_add_devices(microdev_devices, ARRAY_SIZE(microdev_devices));
 }
 
-__initcall(microdev_devices_setup);
-
-void __init platform_setup(void)
-{
-       int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul);
-       const int fpgaRevision = *fpgaRevisionRegister;
-       int * const CacheControlRegister = (int*)CCR;
-
-       printk("SuperH %s board (FPGA rev: 0x%0x, CCR: 0x%0x)\n",
-               get_system_type(), fpgaRevision, *CacheControlRegister);
-}
-
-
-/****************************************************************************/
-
-
-       /*
-        * Setup for the SMSC FDC37C93xAPM
-        */
+/*
+ * Setup for the SMSC FDC37C93xAPM
+ */
 static int __init smsc_superio_setup(void)
 {
 
@@ -412,8 +355,52 @@ static int __init smsc_superio_setup(void)
        return 0;
 }
 
+static void __init microdev_setup(char **cmdline_p)
+{
+       int * const fpgaRevisionRegister = (int*)(MICRODEV_FPGA_GP_BASE + 0x8ul);
+       const int fpgaRevision = *fpgaRevisionRegister;
+       int * const CacheControlRegister = (int*)CCR;
+
+       device_initcall(microdev_devices_setup);
+       device_initcall(smsc_superio_setup);
 
-/* This is grotty, but, because kernel is always referenced on the link line
- * before any devices, this is safe.
+       printk("SuperH %s board (FPGA rev: 0x%0x, CCR: 0x%0x)\n",
+               get_system_type(), fpgaRevision, *CacheControlRegister);
+}
+
+/*
+ * The Machine Vector
  */
-__initcall(smsc_superio_setup);
+struct sh_machine_vector mv_sh4202_microdev __initmv = {
+       .mv_name                = "SH4-202 MicroDev",
+       .mv_setup               = microdev_setup,
+       .mv_nr_irqs             = 72,           /* QQQ need to check this - use the MACRO */
+
+       .mv_inb                 = microdev_inb,
+       .mv_inw                 = microdev_inw,
+       .mv_inl                 = microdev_inl,
+       .mv_outb                = microdev_outb,
+       .mv_outw                = microdev_outw,
+       .mv_outl                = microdev_outl,
+
+       .mv_inb_p               = microdev_inb_p,
+       .mv_inw_p               = microdev_inw_p,
+       .mv_inl_p               = microdev_inl_p,
+       .mv_outb_p              = microdev_outb_p,
+       .mv_outw_p              = microdev_outw_p,
+       .mv_outl_p              = microdev_outl_p,
+
+       .mv_insb                = microdev_insb,
+       .mv_insw                = microdev_insw,
+       .mv_insl                = microdev_insl,
+       .mv_outsb               = microdev_outsb,
+       .mv_outsw               = microdev_outsw,
+       .mv_outsl               = microdev_outsl,
+
+       .mv_init_irq            = init_microdev_irq,
+
+#ifdef CONFIG_HEARTBEAT
+       .mv_heartbeat           = microdev_heartbeat,
+#endif
+};
+ALIAS_MV(sh4202_microdev)
diff --git a/arch/sh/boards/titan/Makefile b/arch/sh/boards/titan/Makefile
new file mode 100644 (file)
index 0000000..08d7537
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the Nimble Microsystems TITAN specific parts of the kernel
+#
+
+obj-y   := setup.o io.o
diff --git a/arch/sh/boards/titan/io.c b/arch/sh/boards/titan/io.c
new file mode 100644 (file)
index 0000000..4730c1d
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ *     I/O routines for Titan
+ */
+#include <linux/pci.h>
+#include <asm/machvec.h>
+#include <asm/addrspace.h>
+#include <asm/titan.h>
+#include <asm/io.h>
+
+static inline unsigned int port2adr(unsigned int port)
+{
+        maybebadio((unsigned long)port);
+        return port;
+}
+
+u8 titan_inb(unsigned long port)
+{
+        if (PXSEG(port))
+                return ctrl_inb(port);
+        else if (is_pci_ioaddr(port))
+                return ctrl_inb(pci_ioaddr(port));
+        return ctrl_inw(port2adr(port)) & 0xff;
+}
+
+u8 titan_inb_p(unsigned long port)
+{
+        u8 v;
+
+        if (PXSEG(port))
+                v = ctrl_inb(port);
+        else if (is_pci_ioaddr(port))
+                v = ctrl_inb(pci_ioaddr(port));
+        else
+                v = ctrl_inw(port2adr(port)) & 0xff;
+        ctrl_delay();
+        return v;
+}
+
+u16 titan_inw(unsigned long port)
+{
+        if (PXSEG(port))
+                return ctrl_inw(port);
+        else if (is_pci_ioaddr(port))
+                return ctrl_inw(pci_ioaddr(port));
+        else if (port >= 0x2000)
+                return ctrl_inw(port2adr(port));
+        else
+                maybebadio(port);
+        return 0;
+}
+
+u32 titan_inl(unsigned long port)
+{
+        if (PXSEG(port))
+                return ctrl_inl(port);
+        else if (is_pci_ioaddr(port))
+                return ctrl_inl(pci_ioaddr(port));
+        else if (port >= 0x2000)
+                return ctrl_inw(port2adr(port));
+        else
+                maybebadio(port);
+        return 0;
+}
+
+void titan_outb(u8 value, unsigned long port)
+{
+        if (PXSEG(port))
+                ctrl_outb(value, port);
+        else if (is_pci_ioaddr(port))
+                ctrl_outb(value, pci_ioaddr(port));
+        else
+                ctrl_outw(value, port2adr(port));
+}
+
+void titan_outb_p(u8 value, unsigned long port)
+{
+        if (PXSEG(port))
+                ctrl_outb(value, port);
+        else if (is_pci_ioaddr(port))
+                ctrl_outb(value, pci_ioaddr(port));
+        else
+                ctrl_outw(value, port2adr(port));
+        ctrl_delay();
+}
+
+void titan_outw(u16 value, unsigned long port)
+{
+        if (PXSEG(port))
+                ctrl_outw(value, port);
+        else if (is_pci_ioaddr(port))
+                ctrl_outw(value, pci_ioaddr(port));
+        else if (port >= 0x2000)
+                ctrl_outw(value, port2adr(port));
+        else
+                maybebadio(port);
+}
+
+void titan_outl(u32 value, unsigned long port)
+{
+        if (PXSEG(port))
+                ctrl_outl(value, port);
+        else if (is_pci_ioaddr(port))
+                ctrl_outl(value, pci_ioaddr(port));
+        else
+                maybebadio(port);
+}
+
+void titan_insl(unsigned long port, void *dst, unsigned long count)
+{
+        maybebadio(port);
+}
+
+void titan_outsl(unsigned long port, const void *src, unsigned long count)
+{
+        maybebadio(port);
+}
+
+void __iomem *titan_ioport_map(unsigned long port, unsigned int size)
+{
+       if (PXSEG(port) || is_pci_memaddr(port))
+               return (void __iomem *)port;
+       else if (is_pci_ioaddr(port))
+               return (void __iomem *)pci_ioaddr(port);
+
+       return (void __iomem *)port2adr(port);
+}
diff --git a/arch/sh/boards/titan/setup.c b/arch/sh/boards/titan/setup.c
new file mode 100644 (file)
index 0000000..52b66d8
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *     Setup for Titan
+ */
+
+#include <linux/init.h>
+#include <asm/irq.h>
+#include <asm/titan.h>
+#include <asm/io.h>
+
+extern void __init pcibios_init_platform(void);
+
+static void __init init_titan_irq(void)
+{
+       /* enable individual interrupt mode for externals */
+       ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
+
+       make_ipr_irq( TITAN_IRQ_WAN,   IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); /* PCIRQ0 */
+       make_ipr_irq( TITAN_IRQ_LAN,   IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); /* PCIRQ1 */
+       make_ipr_irq( TITAN_IRQ_MPCIA, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); /* PCIRQ2 */
+       make_ipr_irq( TITAN_IRQ_USB,   IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); /* PCIRQ3 */
+}
+
+struct sh_machine_vector mv_titan __initmv = {
+       .mv_name =      "Titan",
+
+       .mv_inb =       titan_inb,
+       .mv_inw =       titan_inw,
+       .mv_inl =       titan_inl,
+       .mv_outb =      titan_outb,
+       .mv_outw =      titan_outw,
+       .mv_outl =      titan_outl,
+
+       .mv_inb_p =     titan_inb_p,
+       .mv_inw_p =     titan_inw,
+       .mv_inl_p =     titan_inl,
+       .mv_outb_p =    titan_outb_p,
+       .mv_outw_p =    titan_outw,
+       .mv_outl_p =    titan_outl,
+
+       .mv_insl =      titan_insl,
+       .mv_outsl =     titan_outsl,
+
+       .mv_ioport_map = titan_ioport_map,
+
+       .mv_init_irq =  init_titan_irq,
+       .mv_init_pci =  pcibios_init_platform,
+};
+ALIAS_MV(titan)
index c5e4ed10876befa7665a83e0ba5f84bc24b792fa..1c941370a2e32a8bc0ea9b55a200dd6907be9a42 100644 (file)
  */
 #include <linux/init.h>
 #include <asm/machvec.h>
-#include <asm/irq.h>
 
 struct sh_machine_vector mv_unknown __initmv = {
-       .mv_nr_irqs             = NR_IRQS,
+       .mv_name                = "Unknown",
 };
 ALIAS_MV(unknown)
-
-const char *get_system_type(void)
-{
-       return "Unknown";
-}
-
-void __init platform_setup(void)
-{
-}
-
index 75a6876bf6c6356d3f9f9605c46154211aea82a0..e5f4437900794a66874de91e62a557572f5b0e81 100644 (file)
@@ -18,13 +18,20 @@ endif
 # Assign dummy values if these 2 variables are not defined,
 # in order to suppress error message.
 #
+CONFIG_PAGE_OFFSET     ?= 0x80000000
 CONFIG_MEMORY_START     ?= 0x0c000000
 CONFIG_BOOT_LINK_OFFSET ?= 0x00800000
-IMAGE_OFFSET := $(shell printf "0x%8x" $$[0x80000000+$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)])
+
+IMAGE_OFFSET   := $(shell printf "0x%08x" $$[$(CONFIG_PAGE_OFFSET)  + \
+                                             $(CONFIG_MEMORY_START) + \
+                                             $(CONFIG_BOOT_LINK_OFFSET)])
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
 
 LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds
 
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE
+
+$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
        $(call if_changed,ld)
        @:
 
index 155d139884c34f8b440a7cc8a1f2d33567964c06..0582ca8346b697e99a21f24208e2c3c22231fe86 100644 (file)
@@ -65,6 +65,11 @@ config HD64461_IRQ
 
          Do not change this unless you know what you are doing.
 
+config HD64461_IOBASE
+       hex "HD64461 start address"
+       depends on HD64461
+       default "0xb0000000"
+
 config HD64461_ENABLER
        bool "HD64461 PCMCIA enabler"
        depends on HD64461
@@ -73,7 +78,6 @@ config HD64461_ENABLER
          via the HD64461 companion chip.
          Otherwise, say N.
 
-
 config HD64465_IOBASE
        hex "HD64465 start address"
        depends on HD64465
index ac3062671db7ae122001c862e6d5b94f7469a666..7909a1b7b512a57018ffe7a12bcd34d8eb742072 100644 (file)
@@ -1,11 +1,10 @@
 /*
- *     $Id: io.c,v 1.6 2004/03/16 00:07:50 lethal Exp $
  *     Copyright (C) 2000 YAEGASHI Takeshi
  *     Typical I/O routines for HD64461 system.
  */
 
 #include <asm/io.h>
-#include <asm/hd64461/hd64461.h>
+#include <asm/hd64461.h>
 
 #define MEM_BASE (CONFIG_HD64461_IOBASE - HD64461_STBCR)
 
@@ -54,11 +53,6 @@ static __inline__ unsigned long PORT2ADDR(unsigned long port)
        return 0xa0000000 + (port & 0x1fffffff);
 }
 
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
 unsigned char hd64461_inb(unsigned long port)
 {
        return *(volatile unsigned char*)PORT2ADDR(port);
@@ -67,7 +61,7 @@ unsigned char hd64461_inb(unsigned long port)
 unsigned char hd64461_inb_p(unsigned long port)
 {
        unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
-       delay();
+       ctrl_delay();
        return v;
 }
 
@@ -89,7 +83,7 @@ void hd64461_outb(unsigned char b, unsigned long port)
 void hd64461_outb_p(unsigned char b, unsigned long port)
 {
        *(volatile unsigned char*)PORT2ADDR(port) = b;
-       delay();
+       ctrl_delay();
 }
 
 void hd64461_outw(unsigned short b, unsigned long port)
@@ -144,13 +138,13 @@ void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count)
        while(count--) *addr=*buf++;
 }
 
-unsigned short hd64461_readw(unsigned long addr)
+unsigned short hd64461_readw(void __iomem *addr)
 {
-       return *(volatile unsigned short*)(MEM_BASE+addr);
+       return ctrl_inw(MEM_BASE+(unsigned long __force)addr);
 }
 
-void hd64461_writew(unsigned short b, unsigned long addr)
+void hd64461_writew(unsigned short b, void __iomem *addr)
 {
-       *(volatile unsigned short*)(MEM_BASE+addr) = b;
+       ctrl_outw(b, MEM_BASE+(unsigned long __force)addr);
 }
 
index ad126016720ff227438c356b0a2398a2564756fe..38f1e8171a3abbf361ac628e2b1f63c24c4b9f92 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/irq.h>
-
 #include <asm/io.h>
 #include <asm/irq.h>
-
-#include <asm/hd64461/hd64461.h>
+#include <asm/hd64461.h>
 
 static void disable_hd64461_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short nimr;
        unsigned short mask = 1 << (irq - HD64461_IRQBASE);
 
-       local_irq_save(flags);
        nimr = inw(HD64461_NIMR);
        nimr |= mask;
        outw(nimr, HD64461_NIMR);
-       local_irq_restore(flags);
 }
 
 static void enable_hd64461_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short nimr;
        unsigned short mask = 1 << (irq - HD64461_IRQBASE);
 
-       local_irq_save(flags);
        nimr = inw(HD64461_NIMR);
        nimr &= ~mask;
        outw(nimr, HD64461_NIMR);
-       local_irq_restore(flags);
 }
 
 static void mask_and_ack_hd64461(unsigned int irq)
index d2b2851bc44bcf702ba21c35ca282841401b2b02..30573d3e1966717c46c420703972166625cb785f 100644 (file)
 
 static void disable_hd64465_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short nimr;
        unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
 
        pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask);
-       local_irq_save(flags);
        nimr = inw(HD64465_REG_NIMR);
        nimr |= mask;
        outw(nimr, HD64465_REG_NIMR);
-       local_irq_restore(flags);
 }
 
 
 static void enable_hd64465_irq(unsigned int irq)
 {
-       unsigned long flags;
        unsigned short nimr;
        unsigned short mask = 1 << (irq - HD64465_IRQ_BASE);
 
        pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask);
-       local_irq_save(flags);
        nimr = inw(HD64465_REG_NIMR);
        nimr &= ~mask;
        outw(nimr, HD64465_REG_NIMR);
-       local_irq_restore(flags);
 }
 
 
index 0dc1fb8f9687626a71d6e1905bd52dc049c9e1a3..392c8b12ce36789dea7dbe0b8b3a25084f49371b 100644 (file)
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/rts7751r2d/rts7751r2d.h>
-#include <asm/rts7751r2d/voyagergx_reg.h>
+#include <asm/voyagergx.h>
 
 static void disable_voyagergx_irq(unsigned int irq)
 {
-       unsigned long flags, 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=%x\n", irq, mask);
-       local_irq_save(flags);
         val = inl(VOYAGER_INT_MASK);
         val &= ~mask;
         outl(val, VOYAGER_INT_MASK);
-       local_irq_restore(flags);
 }
 
-
 static void enable_voyagergx_irq(unsigned int irq)
 {
-        unsigned long flags, 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=%x\n", irq, mask);
-        local_irq_save(flags);
         val = inl(VOYAGER_INT_MASK);
         val |= mask;
         outl(val, VOYAGER_INT_MASK);
-        local_irq_restore(flags);
 }
 
-
 static void mask_and_ack_voyagergx(unsigned int irq)
 {
        disable_voyagergx_irq(irq);
@@ -95,7 +88,8 @@ static struct hw_interrupt_type voyagergx_irq_type = {
        .end = end_voyagergx_irq,
 };
 
-static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t voyagergx_interrupt(int irq, void *dev_id,
+                                     struct pt_regs *regs)
 {
        printk(KERN_INFO
               "VoyagerGX: spurious interrupt, status: 0x%x\n",
@@ -103,9 +97,6 @@ static irqreturn_t voyagergx_interrupt(int irq, void *dev_id, struct pt_regs *re
        return IRQ_HANDLED;
 }
 
-
-/*====================================================*/
-
 static struct {
        int (*func)(int, void *);
        void *dev;
index 139ca88ac9e6217709783ca84f629cb3975c4ec6..66b2fedd7ad9308c53648116d56c317a15c3b533 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <asm/io.h>
-#include <asm/rts7751r2d/voyagergx_reg.h>
+#include <asm/voyagergx.h>
 
 static int __init setup_voyagergx(void)
 {
diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig
new file mode 100644 (file)
index 0000000..6b43316
--- /dev/null
@@ -0,0 +1,1373 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.13-sh
+# Sun Sep 11 13:00:46 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+CONFIG_SH_LANDISK=y
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+CONFIG_CPU_SUBTYPE_SH7751R=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+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
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ_BOOL=y
+CONFIG_SH_PCLK_FREQ=33333333
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Kernel features
+#
+CONFIG_KEXEC=y
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_ISA=y
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+CONFIG_PCMCIA_LOAD_CIS=y
+CONFIG_PCMCIA_IOCTL=y
+CONFIG_CARDBUS=y
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=y
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCMCIA_PROBE=y
+CONFIG_PCCARD_NONSTATIC=y
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+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=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# 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_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_NETFILTER_NETLINK is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+# CONFIG_IP_NF_NETBIOS_NS is not set
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+# CONFIG_IP_NF_PPTP is not set
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+# CONFIG_IP_NF_MATCH_DCCP is not set
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+# CONFIG_IP_NF_MATCH_CONNBYTES is not set
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+# CONFIG_IP_NF_MATCH_STRING is not set
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+# CONFIG_IP_NF_TARGET_NFQUEUE is not set
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+# CONFIG_IP_NF_TARGET_TTL is not set
+CONFIG_IP_NF_TARGET_CONNMARK=m
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP 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_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+CONFIG_ATALK=m
+# CONFIG_DEV_APPLETALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
+
+#
+# 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=y
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+# CONFIG_PNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# 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_SX8 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=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# 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
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDESCSI=y
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+CONFIG_BLK_DEV_OFFBOARD=y
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_IDEDMA_ONLYDISK=y
+CONFIG_BLK_DEV_AEC62XX=y
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX 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
+# 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_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+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
+
+#
+# SCSI Transport Attributes
+#
+# 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
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X 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_DPT_I2O is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_PCMCIA_AHA152X is not set
+# CONFIG_PCMCIA_FDOMAIN is not set
+# CONFIG_PCMCIA_NINJA_SCSI is not set
+# CONFIG_PCMCIA_QLOGIC is not set
+# CONFIG_PCMCIA_SYM53C500 is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_RAID6 is not set
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+# CONFIG_BLK_DEV_DM is not set
+
+#
+# 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
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NE2000 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_AC3200 is not set
+# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_CS89x0 is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=y
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# 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
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 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 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+CONFIG_RS5C313_RTC=y
+# CONFIG_GEN_RTC is not set
+# 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
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=m
+
+#
+# Video For Linux
+#
+
+#
+# Video Adapters
+#
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_VIDEO_MXB is not set
+# CONFIG_VIDEO_DPC is not set
+# CONFIG_VIDEO_HEXIUM_ORION is not set
+# CONFIG_VIDEO_HEXIUM_GEMINI is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_RADIO_GEMTEK_PCI is not set
+# CONFIG_RADIO_MAXIRADIO is not set
+# CONFIG_RADIO_MAESTRO is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_RADIO_SF16FMR2 is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FONT_8x16=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES 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_SOUND_ALI5455 is not set
+# CONFIG_SOUND_FORTE is not set
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+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_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT 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_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_OBSOLETE_OSS_USB_DRIVER=y
+CONFIG_USB_AUDIO=m
+# CONFIG_USB_BLUETOOTH_TTY is not set
+CONFIG_USB_MIDI=m
+# CONFIG_USB_ACM is not set
+CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_DPCM=y
+# CONFIG_USB_STORAGE_USBAT is not set
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV 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_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE 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 Multimedia devices
+#
+CONFIG_USB_DABUSB=m
+CONFIG_USB_VICAM=m
+CONFIG_USB_DSBR=m
+CONFIG_USB_IBMCAM=m
+CONFIG_USB_KONICAWC=m
+CONFIG_USB_OV511=m
+CONFIG_USB_SE401=m
+CONFIG_USB_SN9C102=m
+CONFIG_USB_STV680=m
+CONFIG_USB_PWC=m
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+CONFIG_USB_SERIAL_FTDI_SIO=m
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# 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_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_SISUSBVGA_CON=y
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_INOTIFY=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=m
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_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=m
+CONFIG_UFS_FS_WRITE=y
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT 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 is not set
+# 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=y
+# 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 is not set
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_FRAME_POINTER is not set
+CONFIG_SH_STANDARD_BIOS=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/sh/configs/r7780rp_defconfig b/arch/sh/configs/r7780rp_defconfig
new file mode 100644 (file)
index 0000000..d597fc5
--- /dev/null
@@ -0,0 +1,1099 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.15-sh
+# Sat Jan  7 19:47:53 2006
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_LBD 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_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R77703DRP is not set
+CONFIG_SH_R7780RP=y
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+CONFIG_CPU_SUBTYPE_SH7780=y
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_32BIT=y
+CONFIG_HUGETLB_PAGE_SIZE_64K=y
+# CONFIG_HUGETLB_PAGE_SIZE_1MB 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=4
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SH_FPU=y
+CONFIG_SH_STORE_QUEUES=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ_BOOL=y
+CONFIG_SH_PCLK_FREQ=32000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=6
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_KEXEC is not set
+CONFIG_PREEMPT=y
+# CONFIG_SMP is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_INTC2_IRQ=y
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="mem=128M console=ttySC0,115200 root=/dev/hda1"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+# CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+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=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_MULTIPLE_TABLES is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# 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_TUNNEL is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 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
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+# 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_NET_DIVERT 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=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=m
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=m
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+CONFIG_BLK_DEV_IDE_SATA=y
+CONFIG_BLK_DEV_IDEDISK=m
+CONFIG_IDEDISK_MULTI_MODE=y
+# 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=m
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=m
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=m
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+CONFIG_BLK_DEV_AEC62XX=m
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX 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
+CONFIG_BLK_DEV_PDC202XX_NEW=m
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=m
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# 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=m
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# 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
+
+#
+# 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_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA 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_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=m
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX 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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# 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
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# 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
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+CONFIG_NE2000=y
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+CONFIG_8139CP=m
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+CONFIG_8139TOO_8129=y
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+CONFIG_VIA_RHINE=m
+CONFIG_VIA_RHINE_MMIO=y
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=m
+# CONFIG_E1000_NAPI is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_NORTEL_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# 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
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON 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_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# 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
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=m
+# CONFIG_OBSOLETE_OSS_DRIVER is not set
+# CONFIG_SOUND_FUSION 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
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+# 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
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=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=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=y
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_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
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+# 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 is not set
+# 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=y
+# 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
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_DEBUG_VM is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
index d217e44c89a6a4caabc902d1502fe543b20bedfd..fe19feb95ca9a4a918761a23459d284db9c809c6 100644 (file)
@@ -78,6 +78,7 @@ CONFIG_SH_73180_SOLUTION_ENGINE=y
 # CONFIG_SH_SECUREEDGE5410 is not set
 # CONFIG_SH_HS7751RVOIP is not set
 # CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
 # CONFIG_SH_EDOSK7705 is not set
 # CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
diff --git a/arch/sh/configs/se7343_defconfig b/arch/sh/configs/se7343_defconfig
new file mode 100644 (file)
index 0000000..948e507
--- /dev/null
@@ -0,0 +1,997 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Mon Aug  7 20:14:44 2006
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# 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 is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# 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 is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SHMEM is not set
+CONFIG_SLAB=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# 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=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# System type
+#
+CONFIG_SOLUTION_ENGINE=y
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+CONFIG_SH_7343_SOLUTION_ENGINE=y
+# 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
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_7710VOIPGW is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+CONFIG_CPU_SH4A=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+CONFIG_CPU_SUBTYPE_SH7343=y
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x01000000
+CONFIG_32BIT=y
+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=4
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_SH_FPU is not set
+# CONFIG_SH_FPU_EMU is not set
+CONFIG_SH_DSP=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ=27000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+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=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL 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_NET_DIVERT 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=y
+
+#
+# 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=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=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
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# 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_PHYSMAP is not set
+# CONFIG_MTD_SOLUTIONENGINE is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# 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 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 is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI 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_STNIC is not set
+CONFIG_SMC91X=y
+# CONFIG_NE2000 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
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# 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
+#
+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_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+CONFIG_I2C_SH7343=y
+
+#
+# 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 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
+#
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+
+#
+# Video Capture Adapters
+#
+
+#
+# Video Capture Adapters
+#
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+
+#
+# Encoders and Decoders
+#
+# CONFIG_VIDEO_MSP3400 is not set
+# CONFIG_VIDEO_CS53L32A is not set
+# CONFIG_VIDEO_WM8775 is not set
+# CONFIG_VIDEO_WM8739 is not set
+# CONFIG_VIDEO_CX25840 is not set
+# CONFIG_VIDEO_SAA711X is not set
+# CONFIG_VIDEO_SAA7127 is not set
+# CONFIG_VIDEO_UPD64031A is not set
+# CONFIG_VIDEO_UPD64083 is not set
+
+#
+# Radio Adapters
+#
+# CONFIG_RADIO_MAESTRO is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+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_FIRMWARE_EDID=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_EPSON1355 is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+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=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_SEQUENCER=y
+# CONFIG_SND_SEQ_DUMMY is not set
+CONFIG_SND_OSSEMUL=y
+# CONFIG_SND_MIXER_OSS is not set
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_SEQUENCER_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_VIRMIDI is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# SuperH devices
+#
+CONFIG_SH7343_SIU=m
+CONFIG_AK4537_CODEC=y
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI 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
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_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_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# 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_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS 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_JFFS_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_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN 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
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+# CONFIG_NFSD_TCP is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=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 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ 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
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/sh/configs/sh7710voipgw_defconfig b/arch/sh/configs/sh7710voipgw_defconfig
new file mode 100644 (file)
index 0000000..ec9a303
--- /dev/null
@@ -0,0 +1,913 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.17
+# Mon Aug  7 17:07:06 2006
+#
+CONFIG_SUPERH=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# 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 is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_UID16=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# 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 is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SHMEM is not set
+CONFIG_SLAB=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+CONFIG_OBSOLETE_INTERMODULE=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# Block layer
+#
+# 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=y
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_DEFAULT_AS is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# 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
+# CONFIG_SH_HS7751RVOIP is not set
+CONFIG_SH_7710VOIPGW=y
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_SHMIN is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH3=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+CONFIG_CPU_SUBTYPE_SH7710=y
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x00800000
+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=4
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_SH_FPU_EMU is not set
+CONFIG_SH_DSP=y
+# CONFIG_SH_ADC is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ=32768000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_KEXEC is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM 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 is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# 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_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+# CONFIG_IP_NF_CT_ACCT is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
+# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+# CONFIG_IP_NF_IRC is not set
+# CONFIG_IP_NF_NETBIOS_NS is not set
+# CONFIG_IP_NF_TFTP is not set
+# CONFIG_IP_NF_AMANDA is not set
+CONFIG_IP_NF_PPTP=m
+# CONFIG_IP_NF_H323 is not set
+# CONFIG_IP_NF_QUEUE 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+
+#
+# Queueing/Scheduling
+#
+CONFIG_NET_SCH_CBQ=y
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=y
+
+#
+# Classification
+#
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_ROUTE4=y
+CONFIG_NET_CLS_ROUTE=y
+# CONFIG_NET_CLS_FW is not set
+CONFIG_NET_CLS_U32=y
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_CLS_U32_MARK is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_ESTIMATOR=y
+
+#
+# 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=y
+
+#
+# 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 is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=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
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+# 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_PHYSMAP is not set
+# CONFIG_MTD_SOLUTIONENGINE is not set
+CONFIG_MTD_SH7710VOIPGW=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# 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 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 is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI 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 is not set
+# CONFIG_STNIC is not set
+# CONFIG_SMC91X is not set
+# CONFIG_NE2000 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
+
+#
+# Telephony Support
+#
+CONFIG_PHONE=y
+# CONFIG_PHONE_IXJ is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# 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
+#
+# 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
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_V4L2=y
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI 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
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+# CONFIG_RTC_CLASS is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_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_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_INOTIFY is not set
+# 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_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS 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_JFFS_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_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN 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
+
+#
+# Network File Systems
+#
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD 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 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ 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_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
similarity index 50%
rename from arch/mips/configs/ev96100_defconfig
rename to arch/sh/configs/shmin_defconfig
index 0bdc10f1161081f3311fec6deec98f274a5cec4f..382b3bd3963bc171a7b0286bc3f8ece6dffef330 100644 (file)
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc1
-# Thu Jul  6 10:04:05 2006
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-CONFIG_MIPS_EV96100=y
-# CONFIG_MIPS_IVR is not set
-# CONFIG_MIPS_ITE8172 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_V2PCI is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM200_PCI is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
+# Linux kernel version: 2.6.17
+# Wed Aug  2 01:45:03 2006
+#
+CONFIG_SUPERH=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_MIPS_GT64120=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_MIPS_GT96100=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-CONFIG_CPU_RM7000=y
-# CONFIG_CPU_RM9000 is not set
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_R5000=y
-CONFIG_SYS_HAS_CPU_RM7000=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-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=4
-# CONFIG_RESOURCES_64BIT is not set
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PTRACE=y
 
 #
 # Code maturity level options
@@ -167,70 +24,210 @@ CONFIG_INIT_ENV_ARG_LIMIT=32
 #
 CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
+# CONFIG_SWAP is not set
+# CONFIG_SYSVIPC is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
+# CONFIG_SYSCTL is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
-CONFIG_RELAY=y
+# CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_UID16 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_EMBEDDED=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
+# CONFIG_BUG is not set
+# CONFIG_ELF_CORE is not set
+# CONFIG_BASE_FULL is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SHMEM is not set
+# CONFIG_SLAB is not set
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=1
+CONFIG_SLOB=y
+CONFIG_OBSOLETE_INTERMODULE=y
 
 #
 # Loadable module support
 #
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_KMOD is not set
+# CONFIG_MODULES is not set
 
 #
 # Block layer
 #
 # 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=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=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 is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
 
 #
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7709_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_R7780RP is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+CONFIG_SH_SHMIN=y
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH3=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+CONFIG_CPU_SUBTYPE_SH7706=y
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
 #
-CONFIG_HW_HAS_PCI=y
-# CONFIG_PCI is not set
 CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x00800000
+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=4
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_SH_FPU_EMU is not set
+# CONFIG_SH_DSP is not set
+# CONFIG_SH_ADC is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ=32000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_KEXEC is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00210000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,115200 root=1f01 mtdparts=phys_mapped_flash:64k(firm)ro,-(sys) netdev=34,0x300,eth0 "
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -245,8 +242,13 @@ CONFIG_MMU=y
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
 # CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
+
+#
+# Power management options (EXPERIMENTAL)
+#
+# CONFIG_PM is not set
 
 #
 # Networking
@@ -259,16 +261,14 @@ CONFIG_NET=y
 # CONFIG_NETDEBUG is not set
 # CONFIG_PACKET is not set
 CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-CONFIG_NET_KEY=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_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
@@ -279,8 +279,6 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
@@ -288,7 +286,6 @@ CONFIG_TCP_CONG_BIC=y
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
 # CONFIG_NETFILTER is not set
 
 #
@@ -330,13 +327,7 @@ CONFIG_NETWORK_SECMARK=y
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-CONFIG_IEEE80211_SOFTMAC=m
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_IEEE80211 is not set
 
 #
 # Device Drivers
@@ -348,17 +339,92 @@ CONFIG_WIRELESS_EXT=y
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
-# CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
-CONFIG_CONNECTOR=m
+# CONFIG_CONNECTOR is not set
 
 #
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+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
+
+#
+# User Modules And Translation Layers
+#
+# CONFIG_MTD_CHAR is not set
+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
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS 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_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# 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_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xa0000000
+CONFIG_MTD_PHYSMAP_LEN=0x80000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=1
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# 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 is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
 
 #
 # Parallel port support
@@ -373,14 +439,13 @@ CONFIG_CONNECTOR=m
 # Block devices
 #
 # CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP 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_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=m
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -390,7 +455,7 @@ CONFIG_ATA_OVER_ETH=m
 #
 # SCSI device support
 #
-CONFIG_RAID_ATTRS=m
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 
 #
@@ -423,26 +488,16 @@ CONFIG_NETDEVICES=y
 #
 # PHY device support
 #
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 # CONFIG_MII is not set
-CONFIG_MIPS_GT96100ETH=y
-# CONFIG_DM9000 is not set
+# CONFIG_STNIC is not set
+# CONFIG_SMC91X is not set
+CONFIG_NE2000=y
 
 #
 # Ethernet (1000 Mbit)
@@ -485,60 +540,31 @@ CONFIG_MIPS_GT96100ETH=y
 #
 # Input device support
 #
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# 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
+# CONFIG_INPUT is not set
 
 #
 # Hardware I/O ports
 #
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=m
+# 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=y
+# CONFIG_VT 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 is not set
+# CONFIG_SERIAL_8250 is not set
 
 #
 # Non-8250 serial port support
 #
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
@@ -554,7 +580,6 @@ CONFIG_LEGACY_PTY_COUNT=256
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
@@ -611,15 +636,8 @@ CONFIG_VIDEO_V4L2=y
 #
 # 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
-
 #
 # Sound
 #
@@ -672,25 +690,10 @@ CONFIG_DUMMY_CONSOLE=y
 #
 # CONFIG_RTC_CLASS is not set
 
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
 #
 # File systems
 #
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
@@ -699,13 +702,12 @@ CONFIG_EXT2_FS=y
 # 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_INOTIFY is not set
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
+# CONFIG_FUSE_FS is not set
 
 #
 # CD-ROM/DVD Filesystems
@@ -724,12 +726,12 @@ CONFIG_FUSE_FS=m
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-# CONFIG_TMPFS is not set
+# CONFIG_PROC_KCORE is not set
+# CONFIG_SYSFS is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
@@ -741,7 +743,9 @@ CONFIG_RAMFS=y
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -752,19 +756,20 @@ CONFIG_RAMFS=y
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL 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_LOCKD_V4=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_CIFS_DEBUG2 is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -791,48 +796,22 @@ CONFIG_MSDOS_PARTITION=y
 #
 # CONFIG_PRINTK_TIME is not set
 # CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_KERNEL is not set
 CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_DEBUG_FS is not set
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
+# CONFIG_UNWIND_INFO is not set
+CONFIG_SH_STANDARD_BIOS=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_KGDB is not set
 
 #
 # Security options
 #
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
+# CONFIG_KEYS is not set
 
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-# CONFIG_CRYPTO_TEST is not set
+# CONFIG_CRYPTO is not set
 
 #
 # Hardware crypto devices
@@ -842,9 +821,7 @@ CONFIG_CRYPTO_CRC32C=m
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig
new file mode 100644 (file)
index 0000000..1db2904
--- /dev/null
@@ -0,0 +1,1367 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.14-sh
+# Wed Nov  9 00:35:56 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=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_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+# CONFIG_SH_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+CONFIG_SH_TITAN=y
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP6XX is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_UNKNOWN is not set
+
+#
+# Processor selection
+#
+CONFIG_CPU_SH4=y
+
+#
+# SH-2 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+
+#
+# SH-3 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+
+#
+# SH-4 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+CONFIG_CPU_SUBTYPE_SH7751=y
+CONFIG_CPU_SUBTYPE_SH7751R=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+
+#
+# ST40 Processor Support
+#
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+
+#
+# SH-4A Processor Support
+#
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+
+#
+# Memory management options
+#
+CONFIG_MMU=y
+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
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+CONFIG_MEMORY_START=0x08030000
+CONFIG_MEMORY_SIZE=0x7fd0000
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+
+#
+# Timer support
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_PCLK_FREQ_BOOL=y
+CONFIG_SH_PCLK_FREQ=30000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=8
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Kernel features
+#
+# CONFIG_KEXEC is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_SMP is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x009e0000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,38400N81 root=/dev/nfs ip=:::::eth1:autoconf"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+CONFIG_SH_PCIDMA_NONCOHERENT=y
+CONFIG_PCI_AUTO=y
+CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
+CONFIG_PCI_LEGACY_PROC=y
+#CONFIG_PCI_DEBUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+CONFIG_HOTPLUG_PCI=y
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_FWMARK is not set
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_MULTIPATH_CACHED=y
+CONFIG_IP_ROUTE_MULTIPATH_RR=m
+CONFIG_IP_ROUTE_MULTIPATH_RANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_WRANDOM=m
+CONFIG_IP_ROUTE_MULTIPATH_DRR=m
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_TCP_DIAG=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_BIC=y
+
+#
+# IP: Virtual Server Configuration
+#
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+CONFIG_IPV6_PRIVACY=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_INET6_TUNNEL=m
+CONFIG_IPV6_TUNNEL=m
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NETFILTER_NETLINK=m
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CONNTRACK_EVENTS=y
+CONFIG_IP_NF_CONNTRACK_NETLINK=m
+# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_NETBIOS_NS=m
+CONFIG_IP_NF_TFTP=m
+# CONFIG_IP_NF_AMANDA is not set
+CONFIG_IP_NF_PPTP=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+# CONFIG_IP_NF_MATCH_PHYSDEV is not set
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+# CONFIG_IP_NF_MATCH_SCTP is not set
+# CONFIG_IP_NF_MATCH_DCCP is not set
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_CONNBYTES=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_MATCH_STRING=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_TARGET_NFQUEUE=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_PPTP=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+CONFIG_IP6_NF_QUEUE=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_LIMIT=m
+CONFIG_IP6_NF_MATCH_MAC=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_MULTIPORT=m
+CONFIG_IP6_NF_MATCH_OWNER=m
+CONFIG_IP6_NF_MATCH_MARK=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_AHESP=m
+CONFIG_IP6_NF_MATCH_LENGTH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+# CONFIG_IP6_NF_MATCH_PHYSDEV is not set
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_LOG=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_NFQUEUE=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_TARGET_MARK=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_RAW=m
+
+#
+# Bridge: Netfilter Configuration
+#
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+# 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_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_NET_CLS_IND=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_PEDIT=m
+# CONFIG_NET_ACT_SIMP 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=m
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+CONFIG_CONNECTOR=m
+
+#
+# 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_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+CONFIG_BLK_SSFDC=y
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 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=4096
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# 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
+
+#
+# SCSI Transport Attributes
+#
+# 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
+
+#
+# SCSI low-level drivers
+#
+# 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_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA 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_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=m
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_QLA24XX 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
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# 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
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+CONFIG_PHYLIB=m
+CONFIG_PHYCONTROL=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=m
+CONFIG_DAVICOM_PHY=m
+CONFIG_QSEMI_PHY=m
+CONFIG_LXT_PHY=m
+CONFIG_CICADA_PHY=m
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_STNIC is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+CONFIG_CASSINI=m
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NE2000 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+# CONFIG_E100 is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+# CONFIG_8139TOO_PIO is not set
+CONFIG_8139TOO_TUNE_TWISTER=y
+# CONFIG_8139TOO_8129 is not set
+CONFIG_8139_OLD_RX_RESET=y
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+# CONFIG_STRIP is not set
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+# CONFIG_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+CONFIG_PRISM54=m
+# CONFIG_HOSTAP is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# 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
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# 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 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 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# 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
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# 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_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_BLUETOOTH_TTY is not set
+# 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=m
+# 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
+
+#
+# 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_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE 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 Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# 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 is not set
+# CONFIG_USB_ZD1201 is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_KOBIL_SCT is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 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_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TEST is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# SN Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=m
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+CONFIG_FUSE_FS=m
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=m
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+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_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+CONFIG_RELAYFS_FS=m
+
+#
+# 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
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=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=m
+# CONFIG_SMB_NLS_DEFAULT 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=m
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=m
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# 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=m
+CONFIG_NLS_ISO8859_1=m
+# 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=m
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=16
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHEDSTATS is not set
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_AES=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=m
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
+CONFIG_ZLIB_INFLATE=m
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
index 0f15216cd39dea589d2c165739d6b1d5fae6ae15..defc13c37d483c3d4b064f1035609546ba3d4633 100644 (file)
@@ -11,6 +11,8 @@ config SH_DMA
 config NR_ONCHIP_DMA_CHANNELS
        depends on SH_DMA
        int "Number of on-chip DMAC channels"
+       default "8" if CPU_SUBTYPE_SH7750R || CPU_SUBTYPE_SH7751R
+       default "12" if CPU_SUBTYPE_SH7780
        default "4"
        help
          This allows you to specify the number of channels that the on-chip
@@ -52,4 +54,3 @@ config DMA_PAGE_OPS_CHANNEL
          are dual-address capable.
 
 endmenu
-
index 0f866f8789f0de6e4338fab51cb40490290ed055..9cb0709241808b6365e1a024f048722cbffb8a94 100644 (file)
@@ -3,7 +3,7 @@
  *
  * G2 bus DMA support
  *
- * Copyright (C) 2003, 2004  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
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
-
+#include <asm/cacheflush.h>
 #include <asm/mach/sysasic.h>
 #include <asm/mach/dma.h>
 #include <asm/dma.h>
@@ -47,17 +47,31 @@ struct g2_dma_info {
 
 static volatile struct g2_dma_info *g2_dma = (volatile struct g2_dma_info *)0xa05f7800;
 
+#define g2_bytes_remaining(i) \
+       ((g2_dma->channel[i].size - \
+         g2_dma->status[i].size) & 0x0fffffff)
+
 static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       /* FIXME: Do some meaningful completion work here.. */
-       return IRQ_HANDLED;
-}
+       int i;
 
-static struct irqaction g2_dma_irq = {
-       .name           = "g2 DMA handler",
-       .handler        = g2_dma_interrupt,
-       .flags          = IRQF_DISABLED,
-};
+       for (i = 0; i < G2_NR_DMA_CHANNELS; i++) {
+               if (g2_dma->status[i].status & 0x20000000) {
+                       unsigned int bytes = g2_bytes_remaining(i);
+
+                       if (likely(bytes == 0)) {
+                               struct dma_info *info = dev_id;
+                               struct dma_channel *chan = info->channels + i;
+
+                               wake_up(&chan->wait_queue);
+
+                               return IRQ_HANDLED;
+                       }
+               }
+       }
+
+       return IRQ_NONE;
+}
 
 static int g2_enable_dma(struct dma_channel *chan)
 {
@@ -135,8 +149,14 @@ static int g2_xfer_dma(struct dma_channel *chan)
        return 0;
 }
 
+static int g2_get_residue(struct dma_channel *chan)
+{
+       return g2_bytes_remaining(chan->chan);
+}
+
 static struct dma_ops g2_dma_ops = {
        .xfer           = g2_xfer_dma,
+       .get_residue    = g2_get_residue,
 };
 
 static struct dma_info g2_dma_info = {
@@ -148,13 +168,22 @@ static struct dma_info g2_dma_info = {
 
 static int __init g2_dma_init(void)
 {
-       setup_irq(HW_EVENT_G2_DMA, &g2_dma_irq);
+       int ret;
+
+       ret = request_irq(HW_EVENT_G2_DMA, g2_dma_interrupt, IRQF_DISABLED,
+                         "g2 DMA handler", &g2_dma_info);
+       if (unlikely(ret))
+               return -EINVAL;
 
        /* Magic */
        g2_dma->wait_state      = 27;
        g2_dma->magic           = 0x4659404f;
 
-       return register_dmac(&g2_dma_info);
+       ret = register_dmac(&g2_dma_info);
+       if (unlikely(ret != 0))
+               free_irq(HW_EVENT_G2_DMA, 0);
+
+       return ret;
 }
 
 static void __exit g2_dma_exit(void)
@@ -169,4 +198,3 @@ module_exit(g2_dma_exit);
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("G2 bus DMA driver");
 MODULE_LICENSE("GPL");
-
index 30a580aa7cbd04d81f7396616415c1bee24ac91e..3b0b0f60bb3c4293af34c9a6b0f9e610b6c71af6 100644 (file)
@@ -18,8 +18,8 @@
 #include <asm/dma.h>
 #include <asm/io.h>
 
-static unsigned int xfer_complete = 0;
-static int count = 0;
+static unsigned int xfer_complete;
+static int count;
 
 static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -107,4 +107,3 @@ module_exit(pvr2_dma_exit);
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
 MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver");
 MODULE_LICENSE("GPL");
-
index e028a2d2a4eac949d362f1fa7bfec19dc722896d..cbbe8bce3d679fd7d5b77e4f40363fd314dc3dee 100644 (file)
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-
 #include <linux/init.h>
-#include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <asm/dreamcast/dma.h>
-#include <asm/signal.h>
-#include <asm/irq.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 #include "dma-sh.h"
@@ -84,18 +80,23 @@ static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs)
 
 static int sh_dmac_request_dma(struct dma_channel *chan)
 {
-       char name[32];
+       if (unlikely(!chan->flags & DMA_TEI_CAPABLE))
+               return 0;
 
-       snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)",
+       chan->name = kzalloc(32, GFP_KERNEL);
+       if (unlikely(chan->name == NULL))
+               return -ENOMEM;
+       snprintf(chan->name, 32, "DMAC Transfer End (Channel %d)",
                 chan->chan);
 
        return request_irq(get_dmte_irq(chan->chan), dma_tei,
-                          IRQF_DISABLED, name, chan);
+                          IRQF_DISABLED, chan->name, chan);
 }
 
 static void sh_dmac_free_dma(struct dma_channel *chan)
 {
        free_irq(get_dmte_irq(chan->chan), chan);
+       kfree(chan->name);
 }
 
 static void
@@ -259,7 +260,7 @@ static int __init sh_dmac_init(void)
 #ifdef CONFIG_CPU_SH4
        make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY);
        i = request_irq(DMAE_IRQ, dma_err, IRQF_DISABLED, "DMAC Address Error", 0);
-       if (i < 0)
+       if (unlikely(i < 0))
                return i;
 #endif
 
@@ -274,7 +275,7 @@ static int __init sh_dmac_init(void)
         * been set.
         */
        i = dmaor_reset();
-       if (i < 0)
+       if (unlikely(i != 0))
                return i;
 
        return register_dmac(info);
index 365bc16a4a83baee91b0dcbeb0ae9c08776e6336..9e00cb8a39e90365f8745d42f76cae5e2b24d411 100644 (file)
@@ -6,7 +6,8 @@ obj-y                                   += pci.o
 obj-$(CONFIG_PCI_AUTO)                 += pci-auto.o
 
 obj-$(CONFIG_CPU_SUBTYPE_ST40STB1)     += pci-st40.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7751)       += pci-sh7751.o 
+obj-$(CONFIG_CPU_SUBTYPE_SH7751)       += pci-sh7751.o ops-sh4.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780)       += pci-sh7780.o ops-sh4.o
 
 obj-$(CONFIG_SH_DREAMCAST)             += ops-dreamcast.o fixups-dreamcast.o \
                                           dma-dreamcast.o
@@ -14,3 +15,6 @@ 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
+obj-$(CONFIG_SH_TITAN)                 += ops-titan.o
+obj-$(CONFIG_SH_LANDISK)               += ops-landisk.o
index 63b1c6f4b8d255e71fd787b3cc0a1759bb3f6c98..c0af5f7ef4142175cfb1c863827f4b9bbc0e550e 100644 (file)
@@ -4,7 +4,7 @@
  * PCI fixups for the Sega Dreamcast
  *
  * Copyright (C) 2001, 2002  M. R. Brown
- * Copyright (C) 2002, 2003  Paul Mundt
+ * Copyright (C) 2002, 2003, 2006  Paul Mundt
  *
  * This file originally bore the message (with enclosed-$):
  *     Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp
@@ -45,36 +45,16 @@ static void __init gapspci_fixup_resources(struct pci_dev *dev)
                printk("PCI: Failed resource fixup\n");
        }
 }
-
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
 
-void __init pcibios_fixup_bus(struct pci_bus *bus)
+int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-       /* 
-        * We don't have any sub bus to fix up, and this is a rather
-        * stupid place to put general device fixups. Don't do it.
-        * Use the pcibios_fixups table or suffer the consequences.
+       /*
+        * The interrupt routing semantics here are quite trivial.
+        *
+        * We basically only support one interrupt, so we only bother
+        * updating a device's interrupt line with this single shared
+        * interrupt. Keeps routing quite simple, doesn't it?
         */
+       return GAPSPCI_IRQ;
 }
-
-void __init pcibios_fixup_irqs(void)
-{
-       struct pci_dev *dev = 0;
-
-       for_each_pci_dev(dev) {
-               /*
-                * The interrupt routing semantics here are quite trivial.
-                *
-                * We basically only support one interrupt, so we only bother
-                * updating a device's interrupt line with this single shared
-                * interrupt. Keeps routing quite simple, doesn't it?
-                */
-               printk(KERN_NOTICE "PCI: Fixing up IRQ routing for device %s\n",
-                      pci_name(dev));
-
-               dev->irq = GAPSPCI_IRQ;
-
-               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-       }
-}
-
diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
new file mode 100644 (file)
index 0000000..3e321df
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * arch/sh/drivers/pci/fixups-r7780rp.c
+ *
+ * Highlander R7780RP-1 PCI fixups
+ *
+ * Copyright (C) 2003  Lineo uSolutions, Inc.
+ * Copyright (C) 2004 - 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/pci.h>
+#include "pci-sh4.h"
+#include <asm/io.h>
+
+int pci_fixup_pcic(void)
+{
+       pci_write_reg(0x000043ff, SH4_PCIINTM);
+       pci_write_reg(0x0000380f, SH4_PCIAINTM);
+
+       pci_write_reg(0xfbb00047, SH7780_PCICMD);
+       pci_write_reg(0x00000000, SH7780_PCIIBAR);
+
+       pci_write_reg(0x00011912, SH7780_PCISVID);
+       pci_write_reg(0x08000000, SH7780_PCICSCR0);
+       pci_write_reg(0x0000001b, SH7780_PCICSAR0);
+       pci_write_reg(0xfd000000, SH7780_PCICSCR1);
+       pci_write_reg(0x0000000f, SH7780_PCICSAR1);
+
+       pci_write_reg(0xfd000000, SH7780_PCIMBR0);
+       pci_write_reg(0x00fc0000, SH7780_PCIMBMR0);
+
+#ifdef CONFIG_32BIT
+       pci_write_reg(0xc0000000, SH7780_PCIMBR2);
+       pci_write_reg(0x20000000 - SH7780_PCI_IO_SIZE, SH7780_PCIMBMR2);
+#endif
+
+       /* Set IOBR for windows containing area specified in pci.h */
+       pci_write_reg((PCIBIOS_MIN_IO & ~(SH7780_PCI_IO_SIZE - 1)),
+                     SH7780_PCIIOBR);
+       pci_write_reg(((SH7780_PCI_IO_SIZE-1) & (7<<18)), SH7780_PCIIOBMR);
+
+       return 0;
+}
index 0c590fc7a0812f518499fbc099758a9b397241c1..e72ceb560d5b737b2d822524ceb0d9bce2c4c0e7 100644 (file)
@@ -10,8 +10,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
-#include "pci-sh7751.h"
-#include <asm/io.h>
+#include "pci-sh4.h"
 
 #define PCIMCR_MRSET_OFF       0xBFFFFFFF
 #define PCIMCR_RFSH_OFF                0xFFFFFFFB
@@ -22,22 +21,23 @@ int pci_fixup_pcic(void)
 
        bcr1 = inl(SH7751_BCR1);
        bcr1 |= 0x40080000;     /* Enable Bit 19 BREQEN, set PCIC to slave */
-       outl(bcr1, PCI_REG(SH7751_PCIBCR1));
+       pci_write_reg(bcr1, SH4_PCIBCR1);
 
        /* Enable all interrupts, so we known what to fix */
-       outl(0x0000c3ff, PCI_REG(SH7751_PCIINTM));
-       outl(0x0000380f, PCI_REG(SH7751_PCIAINTM));
+       pci_write_reg(0x0000c3ff, SH4_PCIINTM);
+       pci_write_reg(0x0000380f, SH4_PCIAINTM);
 
-       outl(0xfb900047, PCI_REG(SH7751_PCICONF1));
-       outl(0xab000001, PCI_REG(SH7751_PCICONF4));
+       pci_write_reg(0xfb900047, SH7751_PCICONF1);
+       pci_write_reg(0xab000001, SH7751_PCICONF4);
 
        mcr = inl(SH7751_MCR);
        mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
-       outl(mcr, PCI_REG(SH7751_PCIMCR));
+       pci_write_reg(mcr, SH4_PCIMCR);
+
+       pci_write_reg(0x0c000000, SH7751_PCICONF5);
+       pci_write_reg(0xd0000000, SH7751_PCICONF6);
+       pci_write_reg(0x0c000000, SH4_PCILAR0);
+       pci_write_reg(0x00000000, SH4_PCILAR1);
 
-       outl(0x0c000000, PCI_REG(SH7751_PCICONF5));
-       outl(0xd0000000, PCI_REG(SH7751_PCICONF6));
-       outl(0x0c000000, PCI_REG(SH7751_PCILAR0));
-       outl(0x00000000, PCI_REG(SH7751_PCILAR1));
        return 0;
 }
index 57ac26c2171f7f3c20e05da84fa32e6d20a2215c..2e8a18b7ee53e48941bc3671776c01908070e1e0 100644 (file)
@@ -3,11 +3,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 
-/*
- *     IRQ functions
- */
-
-int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
+int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
@@ -17,8 +13,9 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
                case 8: return 5;       /* eth1       */
                case 6: return 2;       /* PCI bridge */
                default:
-                       printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
-                       return 2;
+                       printk(KERN_ERR "PCI: Bad IRQ mapping request "
+                                       "for slot %d\n", slot);
+                       return 2;
                }
        } else {
                switch (pin) {
@@ -32,30 +29,3 @@ int __init pcibios_map_platform_irq(u8 slot, u8 pin, struct pci_dev *dev)
        }
        return irq;
 }
-
-static u8 __init sh03_no_swizzle(struct pci_dev *dev, u8 *pin)
-{
-       /* no swizzling */
-       return PCI_SLOT(dev->devfn);
-}
-
-static int sh03_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       int irq = -1;
-
-       /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
-       irq = pcibios_map_platform_irq(slot, pin, dev);
-       if( irq < 0 ) {
-               pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
-               return irq;
-       }
-
-       pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
-
-       return irq;
-}
-
-void __init pcibios_fixup_irqs(void)
-{
-       pci_fixup_irqs(sh03_no_swizzle, sh03_pci_lookup_irq);
-}
index ae82c6ca05e593932f10d2b5a2ec7dd9a1c81c0c..5da501bd77b56cd281507a2d2c66ea323608b635 100644 (file)
  *
  * PCI initialization for the Hitachi Big Sur Evaluation Board
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/pci.h>
-
 #include <asm/io.h>
-#include "pci-sh7751.h"
+#include "pci-sh4.h"
 #include <asm/bigsur/bigsur.h>
 
 #define BIGSUR_PCI_IO  0x4000
@@ -41,11 +38,11 @@ static struct resource sh7751_mem_resource = {
 extern struct pci_ops sh7751_pci_ops;
 
 struct pci_channel board_pci_channels[] = {
-       { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+       { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
        { 0, }
 };
 
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
        .window0        = {
                .base   = SH7751_CS3_BASE_ADDR,
                .size   = BIGSUR_LSR0_SIZE,
@@ -58,7 +55,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
 };
 
 /*
- * Initialize the Big Sur PCI interface 
+ * 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
@@ -68,15 +65,15 @@ int __init pcibios_init_platform(void)
        return sh7751_pcic_init(&sh7751_pci_map);
 }
 
-int pcibios_map_platform_irq(u8 slot, u8 pin)
+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",
@@ -84,4 +81,3 @@ int pcibios_map_platform_irq(u8 slot, u8 pin)
 
        return irq;
 }
-
diff --git a/arch/sh/drivers/pci/ops-landisk.c b/arch/sh/drivers/pci/ops-landisk.c
new file mode 100644 (file)
index 0000000..ada301c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * arch/sh/drivers/pci/ops-landisk.c
+ *
+ * PCI initialization for the I-O DATA Device, Inc. LANDISK board
+ *
+ * Copyright (C) 2006 kogiidena
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include "pci-sh4.h"
+
+static struct resource sh7751_io_resource = {
+       .name = "SH7751 IO",
+       .start = 0x4000,
+       .end = 0x4000 + SH7751_PCI_IO_SIZE - 1,
+       .flags = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+       .name = "SH7751 mem",
+       .start = SH7751_PCI_MEMORY_BASE,
+       .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+       .flags = IORESOURCE_MEM
+};
+
+struct pci_channel board_pci_channels[] = {
+       {&sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0x3ff},
+       {NULL, NULL, NULL, 0, 0},
+};
+
+static struct sh4_pci_address_map sh7751_pci_map = {
+       .window0 = {
+               .base   = SH7751_CS3_BASE_ADDR,
+               .size   = (64 << 20),   /* 64MB */
+       },
+
+       .flags = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+       return sh7751_pcic_init(&sh7751_pci_map);
+}
+
+int pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+       /*
+        * slot0: pin1-4 = irq5,6,7,8
+        * slot1: pin1-4 = irq6,7,8,5
+        * slot2: pin1-4 = irq7,8,5,6
+        * slot3: pin1-4 = irq8,5,6,7
+        */
+       int irq = ((slot + pin - 1) & 0x3) + 5;
+
+       if ((slot | (pin - 1)) > 0x3) {
+               printk("PCI: Bad IRQ mapping request for slot %d pin %c\n",
+                      slot, pin - 1 + 'A');
+               return -1;
+       }
+       return irq;
+}
diff --git a/arch/sh/drivers/pci/ops-r7780rp.c b/arch/sh/drivers/pci/ops-r7780rp.c
new file mode 100644 (file)
index 0000000..554d5ed
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Author:  Ian DaSilva (idasilva@mvista.com)
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * PCI initialization for the Renesas SH7780 Highlander R7780RP-1 board
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <asm/r7780rp/r7780rp.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+        switch (slot) {
+       case 0: return IRQ_PCISLOT1;            /* PCI Interrupt #1 */
+       case 1: return IRQ_PCISLOT2;            /* PCI Interrupt #2 */
+       case 2: return IRQ_PCISLOT3;            /* PCI Interrupt #3 */
+       case 3: return IRQ_PCISLOT4;            /* PCI Interrupt E4 */
+       default:
+               printk(KERN_ERR "PCI: Bad IRQ mapping "
+                      "request for slot %d, func %d\n", slot, pin-1);
+               return -1;
+       }
+}
+
+static struct resource sh7780_io_resource = {
+       .name   = "SH7780_IO",
+       .start  = 0x2000,
+       .end    = 0x2000 + SH7780_PCI_IO_SIZE - 1,
+       .flags  = IORESOURCE_IO
+};
+
+static struct resource sh7780_mem_resource = {
+       .name   = "SH7780_mem",
+       .start  = SH7780_PCI_MEMORY_BASE,
+       .end    = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1,
+       .flags  = IORESOURCE_MEM
+};
+
+extern struct pci_ops sh7780_pci_ops;
+
+struct pci_channel board_pci_channels[] = {
+       { &sh4_pci_ops, &sh7780_io_resource, &sh7780_mem_resource, 0, 0xff },
+       { NULL, NULL, NULL, 0, 0 },
+};
+EXPORT_SYMBOL(board_pci_channels);
+
+static struct sh4_pci_address_map sh7780_pci_map = {
+       .window0        = {
+               .base   = SH7780_CS2_BASE_ADDR,
+               .size   = 0x04000000,
+       },
+
+       .window1        = {
+               .base   = SH7780_CS3_BASE_ADDR,
+               .size   = 0x04000000,
+       },
+
+       .flags  = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+       return sh7780_pcic_init(&sh7780_pci_map);
+}
index 83171d10141ac5223d1f991ef2fc3c5091695415..88f44e2454244f355d3911753798c324389fecb7 100644 (file)
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/module.h>
-
-#include <asm/io.h>
-#include "pci-sh7751.h"
 #include <asm/rts7751r2d/rts7751r2d.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
 
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
 {
         switch (slot) {
        case 0: return IRQ_PCISLOT1;    /* PCI Extend slot #1 */
@@ -52,12 +51,12 @@ static struct resource sh7751_mem_resource = {
 extern struct pci_ops sh7751_pci_ops;
 
 struct pci_channel board_pci_channels[] = {
-       { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+       { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
        { NULL, NULL, NULL, 0, 0 },
 };
 EXPORT_SYMBOL(board_pci_channels);
 
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
        .window0        = {
                .base   = SH7751_CS3_BASE_ADDR,
                .size   = 0x04000000,
@@ -68,7 +67,7 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
                .size   = 0x00000000,   /* Unused */
        },
 
-       .flags  = SH7751_PCIC_NO_RESET,
+       .flags  = SH4_PCIC_NO_RESET,
 };
 
 int __init pcibios_init_platform(void)
diff --git a/arch/sh/drivers/pci/ops-sh4.c b/arch/sh/drivers/pci/ops-sh4.c
new file mode 100644 (file)
index 0000000..2d43710
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
+ *
+ * Copyright (C) 2002 - 2006  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License v2. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/pci.h>
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include "pci-sh4.h"
+
+/*
+ * Direct access to PCI hardware...
+ */
+#define CONFIG_CMD(bus, devfn, where) \
+       P1SEGADDR((bus->number << 16) | (devfn << 8) | (where & ~3))
+
+static DEFINE_SPINLOCK(sh4_pci_lock);
+
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
+                          int where, int size, u32 *val)
+{
+       unsigned long flags;
+       u32 data;
+
+       /*
+        * PCIPDR may only be accessed as 32 bit words,
+        * so we must do byte alignment by hand
+        */
+       spin_lock_irqsave(&sh4_pci_lock, flags);
+       pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+       data = pci_read_reg(SH4_PCIPDR);
+       spin_unlock_irqrestore(&sh4_pci_lock, flags);
+
+       switch (size) {
+       case 1:
+               *val = (data >> ((where & 3) << 3)) & 0xff;
+               break;
+       case 2:
+               *val = (data >> ((where & 2) << 3)) & 0xffff;
+               break;
+       case 4:
+               *val = data;
+               break;
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * Since SH4 only does 32bit access we'll have to do a read,
+ * mask,write operation.
+ * We'll allow an odd byte offset, though it should be illegal.
+ */
+static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
+                        int where, int size, u32 val)
+{
+       unsigned long flags;
+       int shift;
+       u32 data;
+
+       spin_lock_irqsave(&sh4_pci_lock, flags);
+       pci_write_reg(CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
+       data = pci_read_reg(SH4_PCIPDR);
+       spin_unlock_irqrestore(&sh4_pci_lock, flags);
+
+       switch (size) {
+       case 1:
+               shift = (where & 3) << 3;
+               data &= ~(0xff << shift);
+               data |= ((val & 0xff) << shift);
+               break;
+       case 2:
+               shift = (where & 2) << 3;
+               data &= ~(0xffff << shift);
+               data |= ((val & 0xffff) << shift);
+               break;
+       case 4:
+               data = val;
+               break;
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       pci_write_reg(data, SH4_PCIPDR);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops sh4_pci_ops = {
+       .read           = sh4_pci_read,
+       .write          = sh4_pci_write,
+};
+
+/*
+ * Not really related to pci_ops, but it's common and not worth shoving
+ * somewhere else for now..
+ */
+static unsigned int pci_probe = PCI_PROBE_CONF1;
+
+int __init sh4_pci_check_direct(void)
+{
+       /*
+        * Check if configuration works.
+        */
+       if (pci_probe & PCI_PROBE_CONF1) {
+               unsigned int tmp = pci_read_reg(SH4_PCIPAR);
+
+               pci_write_reg(P1SEG, SH4_PCIPAR);
+
+               if (pci_read_reg(SH4_PCIPAR) == P1SEG) {
+                       pci_write_reg(tmp, SH4_PCIPAR);
+                       printk(KERN_INFO "PCI: Using configuration type 1\n");
+                       request_region(PCI_REG(SH4_PCIPAR), 8, "PCI conf1");
+
+                       return 0;
+               }
+
+               pci_write_reg(tmp, SH4_PCIPAR);
+       }
+
+       pr_debug("PCI: pci_check_direct failed\n");
+       return -EINVAL;
+}
+
+/* Handle generic fixups */
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+       int i;
+
+       /*
+        * PCI IDE controllers use non-standard I/O port decoding, respect it.
+        */
+       if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+               return;
+       pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
+       for(i = 0; i < 4; i++) {
+               struct resource *r = &d->resource[i];
+
+               if ((r->start & ~0x80) == 0x374) {
+                       r->start |= 2;
+                       r->end = r->start;
+               }
+       }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
+
+char * __init pcibios_setup(char *str)
+{
+       if (!strcmp(str, "off")) {
+               pci_probe = 0;
+               return NULL;
+       }
+
+       return str;
+}
index 3cbd14dd28fe709a71e0fc7d5655d72cde034147..53dd893d4e549feddec846c29d8408ab7e865e47 100644 (file)
@@ -2,7 +2,7 @@
  * arch/sh/drivers/pci/ops-snapgear.c
  *
  * Author:  David McCullough <davidm@snapgear.com>
- * 
+ *
  * Ported to new API by Paul Mundt <lethal@linux-sh.org>
  *
  * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
  *
  * PCI initialization for the SnapGear boards
  */
-
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/pci.h>
-
-#include <asm/io.h>
-#include "pci-sh7751.h"
+#include "pci-sh4.h"
 
 #define SNAPGEAR_PCI_IO                0x4000
 #define SNAPGEAR_PCI_MEM       0xfd000000
@@ -43,14 +39,12 @@ static struct resource sh7751_mem_resource = {
        .flags          = IORESOURCE_MEM,
 };
 
-extern struct pci_ops sh7751_pci_ops;
-
 struct pci_channel board_pci_channels[] = {
-       { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+       { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
        { 0, }
 };
 
-static struct sh7751_pci_address_map sh7751_pci_map = {
+static struct sh4_pci_address_map sh7751_pci_map = {
        .window0        = {
                .base   = SH7751_CS2_BASE_ADDR,
                .size   = SNAPGEAR_LSR0_SIZE,
@@ -61,11 +55,11 @@ static struct sh7751_pci_address_map sh7751_pci_map = {
                .size   = SNAPGEAR_LSR1_SIZE,
        },
 
-       .flags  = SH7751_PCIC_NO_RESET,
+       .flags  = SH4_PCIC_NO_RESET,
 };
 
 /*
- * Initialize the SnapGear PCI interface 
+ * Initialize the SnapGear PCI interface
  * Setup hardware to be Central Funtion
  * Copy the BSR regs to the PCI interface
  * Setup PCI windows into local RAM
@@ -75,7 +69,7 @@ int __init pcibios_init_platform(void)
        return sh7751_pcic_init(&sh7751_pci_map);
 }
 
-int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
 {
        int irq = -1;
 
@@ -98,4 +92,3 @@ void __init pcibios_fixup(void)
 {
        /* Nothing to fixup .. */
 }
-
diff --git a/arch/sh/drivers/pci/ops-titan.c b/arch/sh/drivers/pci/ops-titan.c
new file mode 100644 (file)
index 0000000..c6097bc
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * arch/sh/drivers/pci/ops-titan.c
+ *
+ * Ported to new API by Paul Mundt <lethal@linux-sh.org>
+ *
+ * Modified from ops-snapgear.c written by  David McCullough
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * PCI initialization for the Titan boards
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/titan.h>
+#include "pci-sh4.h"
+
+int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
+{
+       int irq = -1;
+
+       switch (slot) {
+       case 0: irq = TITAN_IRQ_WAN;   break;   /* eth0 (WAN) */
+       case 1: irq = TITAN_IRQ_LAN;   break;   /* eth1 (LAN) */
+       case 2: irq = TITAN_IRQ_MPCIA; break;   /* mPCI A */
+       case 3: irq = TITAN_IRQ_MPCIB; break;   /* mPCI B */
+       case 4: irq = TITAN_IRQ_USB;   break;   /* USB */
+       default:
+               printk(KERN_INFO "PCI: Bad IRQ mapping "
+                                "request for slot %d\n", slot);
+               return -1;
+       }
+
+       printk("PCI: Mapping TITAN IRQ for slot %d, pin %c to irq %d\n",
+               slot, pin - 1 + 'A', irq);
+
+       return irq;
+}
+
+static struct resource sh7751_io_resource = {
+       .name   = "SH7751_IO",
+       .start  = SH7751_PCI_IO_BASE,
+       .end    = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1,
+       .flags  = IORESOURCE_IO
+};
+
+static struct resource sh7751_mem_resource = {
+       .name   = "SH7751_mem",
+       .start  = SH7751_PCI_MEMORY_BASE,
+       .end    = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1,
+       .flags  = IORESOURCE_MEM
+};
+
+struct pci_channel board_pci_channels[] = {
+       { &sh4_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff },
+       { NULL, NULL, NULL, 0, 0 },
+};
+EXPORT_SYMBOL(board_pci_channels);
+
+static struct sh4_pci_address_map sh7751_pci_map = {
+       .window0        = {
+               .base   = SH7751_CS2_BASE_ADDR,
+               .size   = SH7751_MEM_REGION_SIZE*2,     /* cs2 and cs3 */
+       },
+
+       .window1        = {
+               .base   = SH7751_CS2_BASE_ADDR,
+               .size   = SH7751_MEM_REGION_SIZE*2,
+       },
+
+       .flags  = SH4_PCIC_NO_RESET,
+};
+
+int __init pcibios_init_platform(void)
+{
+       return sh7751_pcic_init(&sh7751_pci_map);
+}
index 4cef4d1d8c841bedf4dc794140e68728f245b047..ecf16344f94a7347ea389e6dca256d6045787012 100644 (file)
 #include <linux/types.h>
 #include <linux/pci.h>
 
-#undef DEBUG
-#ifdef         DEBUG
+#define        DEBUG
+#ifdef DEBUG
 #define        DBG(x...)       printk(x)
 #else
-#define        DBG(x...)       
+#define        DBG(x...)
 #endif
 
 /*
@@ -102,7 +102,7 @@ static u32 pciauto_upper_iospc;
 static u32 pciauto_lower_memspc;
 static u32 pciauto_upper_memspc;
 
-static void __init 
+static void __init
 pciauto_setup_bars(struct pci_channel *hose,
                   int top_bus,
                   int current_bus,
@@ -116,7 +116,6 @@ pciauto_setup_bars(struct pci_channel *hose,
        int found_mem64 = 0;
 
        for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar+=4) {
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
                u32 bar_addr;
 
                /* Read the old BAR value */
@@ -125,7 +124,6 @@ pciauto_setup_bars(struct pci_channel *hose,
                                        pci_devfn,
                                        bar,
                                        &bar_addr);
-#endif
 
                /* Tickle the BAR and get the response */
                early_write_config_dword(hose, top_bus,
@@ -140,8 +138,7 @@ pciauto_setup_bars(struct pci_channel *hose,
                                        bar,
                                        &bar_response);
 
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
-               /* 
+               /*
                 * Write the old BAR value back out, only update the BAR
                 * if we implicitly want resources to be updated, which
                 * is done by the generic code further down. -- PFM.
@@ -151,7 +148,6 @@ pciauto_setup_bars(struct pci_channel *hose,
                                         pci_devfn,
                                         bar,
                                         bar_addr);
-#endif
 
                /* If BAR is not implemented go to the next BAR */
                if (!bar_response)
@@ -177,7 +173,7 @@ retry:
                            PCI_BASE_ADDRESS_MEM_TYPE_64)
                                found_mem64 = 1;
 
-                       addr_mask = PCI_BASE_ADDRESS_MEM_MASK;          
+                       addr_mask = PCI_BASE_ADDRESS_MEM_MASK;
                        upper_limit = &pciauto_upper_memspc;
                        lower_limit = &pciauto_lower_memspc;
                        DBG("        Mem");
@@ -193,22 +189,22 @@ retry:
                if ((bar_value + bar_size) > *upper_limit) {
                        if (bar_response & PCI_BASE_ADDRESS_SPACE) {
                                if (io_resource_inuse->child) {
-                                       io_resource_inuse = 
+                                       io_resource_inuse =
                                                io_resource_inuse->child;
-                                       pciauto_lower_iospc = 
+                                       pciauto_lower_iospc =
                                                io_resource_inuse->start;
-                                       pciauto_upper_iospc = 
+                                       pciauto_upper_iospc =
                                                io_resource_inuse->end + 1;
                                        goto retry;
                                }
 
                        } else {
                                if (mem_resource_inuse->child) {
-                                       mem_resource_inuse = 
+                                       mem_resource_inuse =
                                                mem_resource_inuse->child;
-                                       pciauto_lower_memspc = 
+                                       pciauto_lower_memspc =
                                                mem_resource_inuse->start;
-                                       pciauto_upper_memspc = 
+                                       pciauto_upper_memspc =
                                                mem_resource_inuse->end + 1;
                                        goto retry;
                                }
@@ -230,7 +226,7 @@ retry:
                 * If we are a 64-bit decoder then increment to the
                 * upper 32 bits of the bar and force it to locate
                 * in the lower 4GB of memory.
-                */ 
+                */
                if (found_mem64) {
                        bar += 4;
                        early_write_config_dword(hose, top_bus,
@@ -362,7 +358,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
 {
        u32 temp;
 
-#if !defined(CONFIG_SH_HS7751RVOIP) && !defined(CONFIG_SH_RTS7751R2D)
        /*
         * [jsun] we always bump up baselines a little, so that if there
         * nothing behind P2P bridge, we don't wind up overlapping IO/MEM
@@ -370,7 +365,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
         */
        pciauto_lower_memspc += 1;
        pciauto_lower_iospc += 1;
-#endif
 
        /*
         * Configure subordinate bus number.  The PCI subsystem
@@ -396,11 +390,6 @@ pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose,
         * configured by this routine to happily live behind a
         * P2P bridge in a system.
         */
-#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
-       pciauto_lower_memspc += 0x00400000;
-       pciauto_lower_iospc += 0x00004000;
-#endif
-
        /* Align memory and I/O to 4KB and 4 byte boundaries. */
        pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1))
                & ~(0x1000 - 1);
@@ -433,12 +422,12 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
        int devfn_stop = 0xff;
 
        sub_bus = current_bus;
-       
+
        if (hose->first_devfn)
                devfn_start = hose->first_devfn;
        if (hose->last_devfn)
                devfn_stop = hose->last_devfn;
-       
+
        for (pci_devfn=devfn_start; pci_devfn<devfn_stop; pci_devfn++) {
 
                if (PCI_FUNC(pci_devfn) && !found_multi)
@@ -471,9 +460,6 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
                if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
                        DBG("        Bridge: primary=%.2x, secondary=%.2x\n",
                                current_bus, sub_bus + 1);
-#if defined(CONFIG_SH_HS7751RVOIP) || defined(CONFIG_SH_RTS7751R2D)
-                       pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_1);
-#endif
                        pciauto_prescan_setup_bridge(hose, top_bus, current_bus,
                                                     pci_devfn, sub_bus);
                        DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
@@ -490,10 +476,10 @@ pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus)
                        DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn));
                        /* Place CardBus Socket/ExCA registers */
                        pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, PCI_BASE_ADDRESS_0);
+
                        pciauto_prescan_setup_cardbus_bridge(hose, top_bus,
                                        current_bus, pci_devfn, sub_bus);
+
                        DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n",
                                sub_bus + 1,
                                pciauto_lower_iospc, pciauto_lower_memspc);
diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h
new file mode 100644 (file)
index 0000000..5a61d60
--- /dev/null
@@ -0,0 +1,180 @@
+#ifndef __PCI_SH4_H
+#define __PCI_SH4_H
+
+#ifdef CONFIG_CPU_SUBTYPE_SH7780
+#include "pci-sh7780.h"
+#else
+#include "pci-sh7751.h"
+#endif
+
+#include <asm/io.h>
+
+/* startup values */
+#define PCI_PROBE_BIOS         1
+#define PCI_PROBE_CONF1                2
+#define PCI_PROBE_CONF2                4
+#define PCI_NO_SORT            0x100
+#define PCI_BIOS_SORT          0x200
+#define PCI_NO_CHECKS          0x400
+#define PCI_ASSIGN_ROMS                0x1000
+#define PCI_BIOS_IRQ_SCAN      0x2000
+
+#define SH4_PCICR              0x100           /* PCI Control Register */
+  #define SH4_PCICR_PREFIX       0xA5000000    /* CR prefix for write */
+  #define SH4_PCICR_FTO                  0x00000400    /* TRDY/IRDY Enable */
+  #define SH4_PCICR_TRSB         0x00000200    /* Target Read Single */
+  #define SH4_PCICR_BSWP         0x00000100    /* Target Byte Swap */
+  #define SH4_PCICR_PLUP         0x00000080    /* Enable PCI Pullup */
+  #define SH4_PCICR_ARBM         0x00000040    /* PCI Arbitration Mode */
+  #define SH4_PCICR_MD           0x00000030    /* MD9 and MD10 status */
+  #define SH4_PCICR_SERR         0x00000008    /* SERR output assert */
+  #define SH4_PCICR_INTA         0x00000004    /* INTA output assert */
+  #define SH4_PCICR_PRST         0x00000002    /* PCI Reset Assert */
+  #define SH4_PCICR_CFIN         0x00000001    /* Central Fun. Init Done */
+#define SH4_PCILSR0            0x104           /* PCI Local Space Register0 */
+#define SH4_PCILSR1            0x108           /* PCI Local Space Register1 */
+#define SH4_PCILAR0            0x10C           /* PCI Local Addr Register1 */
+#define SH4_PCILAR1            0x110           /* PCI Local Addr Register1 */
+#define SH4_PCIINT             0x114           /* PCI Interrupt Register */
+  #define SH4_PCIINT_MLCK        0x00008000    /* Master Lock Error */
+  #define SH4_PCIINT_TABT        0x00004000    /* Target Abort Error */
+  #define SH4_PCIINT_TRET        0x00000200    /* Target Retry Error */
+  #define SH4_PCIINT_MFDE        0x00000100    /* Master Func. Disable Error */
+  #define SH4_PCIINT_PRTY        0x00000080    /* Address Parity Error */
+  #define SH4_PCIINT_SERR        0x00000040    /* SERR Detection Error */
+  #define SH4_PCIINT_TWDP        0x00000020    /* Tgt. Write Parity Error */
+  #define SH4_PCIINT_TRDP        0x00000010    /* Tgt. Read Parity Err Det. */
+  #define SH4_PCIINT_MTABT       0x00000008    /* Master-Tgt. Abort Error */
+  #define SH4_PCIINT_MMABT       0x00000004    /* Master-Master Abort Error */
+  #define SH4_PCIINT_MWPD        0x00000002    /* Master Write PERR Detect */
+  #define SH4_PCIINT_MRPD        0x00000001    /* Master Read PERR Detect */
+#define SH4_PCIINTM            0x118           /* PCI Interrupt Mask */
+#define SH4_PCIALR             0x11C           /* Error Address Register */
+#define SH4_PCICLR             0x120           /* Error Command/Data */
+  #define SH4_PCICLR_MPIO        0x80000000
+  #define SH4_PCICLR_MDMA0       0x40000000    /* DMA0 Transfer Error */
+  #define SH4_PCICLR_MDMA1       0x20000000    /* DMA1 Transfer Error */
+  #define SH4_PCICLR_MDMA2       0x10000000    /* DMA2 Transfer Error */
+  #define SH4_PCICLR_MDMA3       0x08000000    /* DMA3 Transfer Error */
+  #define SH4_PCICLR_TGT         0x04000000    /* Target Transfer Error */
+  #define SH4_PCICLR_CMDL        0x0000000F    /* PCI Command at Error */
+#define SH4_PCIAINT            0x130           /* Arbiter Interrupt Register */
+  #define SH4_PCIAINT_MBKN       0x00002000    /* Master Broken Interrupt */
+  #define SH4_PCIAINT_TBTO       0x00001000    /* Target Bus Time Out */
+  #define SH4_PCIAINT_MBTO       0x00001000    /* Master Bus Time Out */
+  #define SH4_PCIAINT_TABT       0x00000008    /* Target Abort */
+  #define SH4_PCIAINT_MABT       0x00000004    /* Master Abort */
+  #define SH4_PCIAINT_RDPE       0x00000002    /* Read Data Parity Error */
+  #define SH4_PCIAINT_WDPE       0x00000001    /* Write Data Parity Error */
+#define SH4_PCIAINTM            0x134          /* Arbiter Int. Mask Register */
+#define SH4_PCIBMLR            0x138           /* Error Bus Master Register */
+  #define SH4_PCIBMLR_REQ4       0x00000010    /* REQ4 bus master at error */
+  #define SH4_PCIBMLR_REQ3       0x00000008    /* REQ3 bus master at error */
+  #define SH4_PCIBMLR_REQ2       0x00000004    /* REQ2 bus master at error */
+  #define SH4_PCIBMLR_REQ1       0x00000002    /* REQ1 bus master at error */
+  #define SH4_PCIBMLR_REQ0       0x00000001    /* REQ0 bus master at error */
+#define SH4_PCIDMABT           0x140           /* DMA Transfer Arb. Register */
+  #define SH4_PCIDMABT_RRBN      0x00000001    /* DMA Arbitor Round-Robin */
+#define SH4_PCIDPA0            0x180           /* DMA0 Transfer Addr. */
+#define SH4_PCIDLA0            0x184           /* DMA0 Local Addr. */
+#define SH4_PCIDTC0            0x188           /* DMA0 Transfer Cnt. */
+#define SH4_PCIDCR0            0x18C           /* DMA0 Control Register */
+  #define SH4_PCIDCR_ALGN        0x00000600    /* DMA Alignment Mode */
+  #define SH4_PCIDCR_MAST        0x00000100    /* DMA Termination Type */
+  #define SH4_PCIDCR_INTM        0x00000080    /* DMA Interrupt Done Mask*/
+  #define SH4_PCIDCR_INTS        0x00000040    /* DMA Interrupt Done Status */
+  #define SH4_PCIDCR_LHLD        0x00000020    /* Local Address Control */
+  #define SH4_PCIDCR_PHLD        0x00000010    /* PCI Address Control*/
+  #define SH4_PCIDCR_IOSEL       0x00000008    /* PCI Address Space Type */
+  #define SH4_PCIDCR_DIR         0x00000004    /* DMA Transfer Direction */
+  #define SH4_PCIDCR_STOP        0x00000002    /* Force DMA Stop */
+  #define SH4_PCIDCR_STRT        0x00000001    /* DMA Start */
+#define SH4_PCIDPA1            0x190           /* DMA1 Transfer Addr. */
+#define SH4_PCIDLA1            0x194           /* DMA1 Local Addr. */
+#define SH4_PCIDTC1            0x198           /* DMA1 Transfer Cnt. */
+#define SH4_PCIDCR1            0x19C           /* DMA1 Control Register */
+#define SH4_PCIDPA2            0x1A0           /* DMA2 Transfer Addr. */
+#define SH4_PCIDLA2            0x1A4           /* DMA2 Local Addr. */
+#define SH4_PCIDTC2            0x1A8           /* DMA2 Transfer Cnt. */
+#define SH4_PCIDCR2            0x1AC           /* DMA2 Control Register */
+#define SH4_PCIDPA3            0x1B0           /* DMA3 Transfer Addr. */
+#define SH4_PCIDLA3            0x1B4           /* DMA3 Local Addr. */
+#define SH4_PCIDTC3            0x1B8           /* DMA3 Transfer Cnt. */
+#define SH4_PCIDCR3            0x1BC           /* DMA3 Control Register */
+#define SH4_PCIPAR             0x1C0           /* PIO Address Register */
+  #define SH4_PCIPAR_CFGEN       0x80000000    /* Configuration Enable */
+  #define SH4_PCIPAR_BUSNO       0x00FF0000    /* Config. Bus Number */
+  #define SH4_PCIPAR_DEVNO       0x0000FF00    /* Config. Device Number */
+  #define SH4_PCIPAR_REGAD       0x000000FC    /* Register Address Number */
+#define SH4_PCIMBR             0x1C4           /* Memory Base Address */
+  #define SH4_PCIMBR_MASK        0xFF000000    /* Memory Space Mask */
+  #define SH4_PCIMBR_LOCK        0x00000001    /* Lock Memory Space */
+#define SH4_PCIIOBR            0x1C8           /* I/O Base Address Register */
+  #define SH4_PCIIOBR_MASK       0xFFFC0000    /* IO Space Mask */
+  #define SH4_PCIIOBR_LOCK       0x00000001    /* Lock IO Space */
+#define SH4_PCIPINT            0x1CC           /* Power Mgmnt Int. Register */
+  #define SH4_PCIPINT_D3         0x00000002    /* D3 Pwr Mgmt. Interrupt */
+  #define SH4_PCIPINT_D0         0x00000001    /* D0 Pwr Mgmt. Interrupt */
+#define SH4_PCIPINTM           0x1D0           /* Power Mgmnt Mask Register */
+#define SH4_PCICLKR            0x1D4           /* Clock Ctrl. Register */
+  #define SH4_PCICLKR_PCSTP      0x00000002    /* PCI Clock Stop */
+  #define SH4_PCICLKR_BCSTP      0x00000001    /* BCLK Clock Stop */
+/* For definitions of BCR, MCR see ... */
+#define SH4_PCIBCR1            0x1E0           /* Memory BCR1 Register */
+  #define SH4_PCIMBR0          SH4_PCIBCR1
+#define SH4_PCIBCR2            0x1E4           /* Memory BCR2 Register */
+  #define SH4_PCIMBMR0         SH4_PCIBCR2
+#define SH4_PCIWCR1            0x1E8           /* Wait Control 1 Register */
+#define SH4_PCIWCR2            0x1EC           /* Wait Control 2 Register */
+#define SH4_PCIWCR3            0x1F0           /* Wait Control 3 Register */
+  #define SH4_PCIMBR2          SH4_PCIWCR3
+#define SH4_PCIMCR             0x1F4           /* Memory Control Register */
+#define SH4_PCIBCR3            0x1f8           /* Memory BCR3 Register */
+#define SH4_PCIPCTR             0x200          /* Port Control Register */
+  #define SH4_PCIPCTR_P2EN       0x000400000   /* Port 2 Enable */
+  #define SH4_PCIPCTR_P1EN       0x000200000   /* Port 1 Enable */
+  #define SH4_PCIPCTR_P0EN       0x000100000   /* Port 0 Enable */
+  #define SH4_PCIPCTR_P2UP       0x000000020   /* Port2 Pull Up Enable */
+  #define SH4_PCIPCTR_P2IO       0x000000010   /* Port2 Output Enable */
+  #define SH4_PCIPCTR_P1UP       0x000000008   /* Port1 Pull Up Enable */
+  #define SH4_PCIPCTR_P1IO       0x000000004   /* Port1 Output Enable */
+  #define SH4_PCIPCTR_P0UP       0x000000002   /* Port0 Pull Up Enable */
+  #define SH4_PCIPCTR_P0IO       0x000000001   /* Port0 Output Enable */
+#define SH4_PCIPDTR            0x204           /* Port Data Register */
+  #define SH4_PCIPDTR_PB5        0x000000020   /* Port 5 Enable */
+  #define SH4_PCIPDTR_PB4        0x000000010   /* Port 4 Enable */
+  #define SH4_PCIPDTR_PB3        0x000000008   /* Port 3 Enable */
+  #define SH4_PCIPDTR_PB2        0x000000004   /* Port 2 Enable */
+  #define SH4_PCIPDTR_PB1        0x000000002   /* Port 1 Enable */
+  #define SH4_PCIPDTR_PB0        0x000000001   /* Port 0 Enable */
+#define SH4_PCIPDR             0x220           /* Port IO Data Register */
+
+/* Flags */
+#define SH4_PCIC_NO_RESET      0x0001
+
+/* arch/sh/kernel/drivers/pci/ops-sh4.c */
+extern struct pci_ops sh4_pci_ops;
+int sh4_pci_check_direct(void);
+int pci_fixup_pcic(void);
+
+struct sh4_pci_address_space {
+       unsigned long base;
+       unsigned long size;
+};
+
+struct sh4_pci_address_map {
+       struct sh4_pci_address_space window0;
+       struct sh4_pci_address_space window1;
+       unsigned long flags;
+};
+
+static inline void pci_write_reg(unsigned long val, unsigned long reg)
+{
+       outl(val, PCI_REG(reg));
+}
+
+static inline unsigned long pci_read_reg(unsigned long reg)
+{
+       return inl(PCI_REG(reg));
+}
+#endif /* __PCI_SH4_H */
index 682f3dae305db3a0aa15c1a1b7804ae67e7c7152..dbe837884983285c302cc60d64e900fbd7ccc94c 100644 (file)
 
 #undef DEBUG
 
-#include <linux/types.h>
-#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
+#include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/irq.h>
 #include <linux/delay.h>
-
-#include <asm/machvec.h>
+#include "pci-sh4.h"
+#include <asm/addrspace.h>
 #include <asm/io.h>
-#include "pci-sh7751.h"
-
-static unsigned int pci_probe = PCI_PROBE_CONF1;
-extern int pci_fixup_pcic(void);
-
-void pcibios_fixup_irqs(void) __attribute__ ((weak));
-
-/*
- * Direct access to PCI hardware...
- */
-
-#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
-
-/*
- * Functions for accessing PCI configuration space with type 1 accesses
- */
-static int sh7751_pci_read(struct pci_bus *bus, unsigned int devfn,
-                          int where, int size, u32 *val)
-{
-       unsigned long flags;
-       u32 data;
-
-       /* 
-        * PCIPDR may only be accessed as 32 bit words, 
-        * so we must do byte alignment by hand 
-        */
-       local_irq_save(flags);
-       outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR));
-       data = inl(PCI_REG(SH7751_PCIPDR));
-       local_irq_restore(flags);
-
-       switch (size) {
-       case 1:
-               *val = (data >> ((where & 3) << 3)) & 0xff;
-               break;
-       case 2:
-               *val = (data >> ((where & 2) << 3)) & 0xffff;
-               break;
-       case 4:
-               *val = data;
-               break;
-       default:
-               return PCIBIOS_FUNC_NOT_SUPPORTED;
-       }
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-/* 
- * Since SH7751 only does 32bit access we'll have to do a read,
- * mask,write operation.
- * We'll allow an odd byte offset, though it should be illegal.
- */ 
-static int sh7751_pci_write(struct pci_bus *bus, unsigned int devfn,
-                           int where, int size, u32 val)
-{
-       unsigned long flags;
-       int shift;
-       u32 data;
-
-       local_irq_save(flags);
-       outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR));
-       data = inl(PCI_REG(SH7751_PCIPDR));
-       local_irq_restore(flags);
-
-       switch (size) {
-       case 1:
-               shift = (where & 3) << 3;
-               data &= ~(0xff << shift);
-               data |= ((val & 0xff) << shift);
-               break;
-       case 2:
-               shift = (where & 2) << 3;
-               data &= ~(0xffff << shift);
-               data |= ((val & 0xffff) << shift);
-               break;
-       case 4:
-               data = val;
-               break;
-       default:
-               return PCIBIOS_FUNC_NOT_SUPPORTED;
-       }
-
-       outl(data, PCI_REG(SH7751_PCIPDR));
-
-       return PCIBIOS_SUCCESSFUL;
-}
-
-#undef CONFIG_CMD
-
-struct pci_ops sh7751_pci_ops = {
-       .read           = sh7751_pci_read,
-       .write          = sh7751_pci_write,
-};
-
-static int __init pci_check_direct(void)
-{
-       unsigned int tmp, id;
-
-       /* check for SH7751/SH7751R hardware */
-       id = inl(SH7751_PCIREG_BASE+SH7751_PCICONF0);
-       if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
-           id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
-               pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
-               return -ENODEV;
-       }
-
-       /*
-        * Check if configuration works.
-        */
-       if (pci_probe & PCI_PROBE_CONF1) {
-               tmp = inl (PCI_REG(SH7751_PCIPAR));
-               outl (0x80000000, PCI_REG(SH7751_PCIPAR));
-               if (inl (PCI_REG(SH7751_PCIPAR)) == 0x80000000) {
-                       outl (tmp, PCI_REG(SH7751_PCIPAR));
-                       printk(KERN_INFO "PCI: Using configuration type 1\n");
-                       request_region(PCI_REG(SH7751_PCIPAR), 8, "PCI conf1");
-                       return 0;
-               }
-               outl (tmp, PCI_REG(SH7751_PCIPAR));
-       }
-
-       pr_debug("PCI: pci_check_direct failed\n");
-       return -EINVAL;
-}
-
-/***************************************************************************************/
-
-/*
- *  Handle bus scanning and fixups ....
- */
-
-static void __init pci_fixup_ide_bases(struct pci_dev *d)
-{
-       int i;
-
-       /*
-        * PCI IDE controllers use non-standard I/O port decoding, respect it.
-        */
-       if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
-               return;
-       pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
-       for(i=0; i<4; i++) {
-               struct resource *r = &d->resource[i];
-               if ((r->start & ~0x80) == 0x374) {
-                       r->start |= 2;
-                       r->end = r->start;
-               }
-       }
-}
-
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
-
-/*
- *  Called after each bus is probed, but before its children
- *  are examined.
- */
-
-void __init pcibios_fixup_bus(struct pci_bus *b)
-{
-       pci_read_bridge_bases(b);
-}
 
 /*
  * Initialization. Try all known PCI access methods. Note that we support
@@ -196,25 +30,29 @@ void __init pcibios_fixup_bus(struct pci_bus *b)
  * to access config space.
  * 
  * Note that the platform specific initialization (BSC registers, and memory
- * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it
- * exitst and via the platform defined function pcibios_init_platform().  
- * See pci_bigsur.c for implementation;
- * 
- * The BIOS version of the pci functions is not yet implemented but it is left
- * in for completeness.  Currently an error will be genereated at compile time. 
+ * space mapping) will be called via the platform defined function
+ * pcibios_init_platform().
  */
-
 static int __init sh7751_pci_init(void)
 {
+       unsigned int id;
        int ret;
 
        pr_debug("PCI: Starting intialization.\n");
-       if ((ret = pci_check_direct()) != 0)
+
+       /* check for SH7751/SH7751R hardware */
+       id = pci_read_reg(SH7751_PCICONF0);
+       if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) &&
+           id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) {
+               pr_debug("PCI: This is not an SH7751(R) (%x)\n", id);
+               return -ENODEV;
+       }
+
+       if ((ret = sh4_pci_check_direct()) != 0)
                return ret;
 
        return pcibios_init_platform();
 }
-
 subsys_initcall(sh7751_pci_init);
 
 static int __init __area_sdram_check(unsigned int area)
@@ -223,26 +61,26 @@ static int __init __area_sdram_check(unsigned int area)
 
        word = inl(SH7751_BCR1);
        /* check BCR for SDRAM in area */
-       if(((word >> area) & 1) == 0) {
+       if (((word >> area) & 1) == 0) {
                printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%x\n",
                       area, word);
                return 0;
        }
-       outl(word, PCI_REG(SH7751_PCIBCR1));
+       pci_write_reg(word, SH4_PCIBCR1);
 
        word = (u16)inw(SH7751_BCR2);
        /* check BCR2 for 32bit SDRAM interface*/
-       if(((word >> (area << 1)) & 0x3) != 0x3) {
+       if (((word >> (area << 1)) & 0x3) != 0x3) {
                printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%x\n",
                       area, word);
                return 0;
        }
-       outl(word, PCI_REG(SH7751_PCIBCR2));
+       pci_write_reg(word, SH4_PCIBCR2);
 
        return 1;
 }
 
-int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
+int __init sh7751_pcic_init(struct sh4_pci_address_map *map)
 {
        u32 reg;
        u32 word;
@@ -251,39 +89,39 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
        reg = inl(SH7751_BCR1);
        reg |= 0x80000;
        outl(reg, SH7751_BCR1);
-       
+
        /* Turn the clocks back on (not done in reset)*/
-       outl(0, PCI_REG(SH7751_PCICLKR));
+       pci_write_reg(0, SH4_PCICLKR);
        /* Clear Powerdown IRQ's (not done in reset) */
-       word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0;
-       outl(word, PCI_REG(SH7751_PCIPINT));
+       word = SH4_PCIPINT_D3 | SH4_PCIPINT_D0;
+       pci_write_reg(word, SH4_PCIPINT);
 
        /*
         * This code is unused for some boards as it is done in the
         * bootloader and doing it here means the MAC addresses loaded
         * by the bootloader get lost.
         */
-       if (!(map->flags & SH7751_PCIC_NO_RESET)) {
+       if (!(map->flags & SH4_PCIC_NO_RESET)) {
                /* toggle PCI reset pin */
-               word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST;
-               outl(word,PCI_REG(SH7751_PCICR));
+               word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
+               pci_write_reg(word, SH4_PCICR);
                /* Wait for a long time... not 1 sec. but long enough */
                mdelay(100);
-               word = SH7751_PCICR_PREFIX;
-               outl(word,PCI_REG(SH7751_PCICR));
+               word = SH4_PCICR_PREFIX;
+               pci_write_reg(word, SH4_PCICR);
        }
-       
+
        /* set the command/status bits to:
         * Wait Cycle Control + Parity Enable + Bus Master +
         * Mem space enable
         */
        word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER | 
               SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
-       outl(word, PCI_REG(SH7751_PCICONF1));
+       pci_write_reg(word, SH7751_PCICONF1);
 
        /* define this host as the host bridge */
-       word = SH7751_PCI_HOST_BRIDGE << 24;
-       outl(word, PCI_REG(SH7751_PCICONF2));
+       word = PCI_BASE_CLASS_BRIDGE << 24;
+       pci_write_reg(word, SH7751_PCICONF2);
 
        /* Set IO and Mem windows to local address 
         * Make PCI and local address the same for easy 1 to 1 mapping 
@@ -291,46 +129,49 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
         * Window1 = map->window1.size @ cached area base = SDRAM 
         */
        word = map->window0.size - 1;
-       outl(word, PCI_REG(SH7751_PCILSR0));
+       pci_write_reg(word, SH4_PCILSR0);
        word = map->window1.size - 1;
-       outl(word, PCI_REG(SH7751_PCILSR1));
+       pci_write_reg(word, SH4_PCILSR1);
        /* Set the values on window 0 PCI config registers */
        word = P2SEGADDR(map->window0.base);
-       outl(word, PCI_REG(SH7751_PCILAR0));
-       outl(word, PCI_REG(SH7751_PCICONF5));
+       pci_write_reg(word, SH4_PCILAR0);
+       pci_write_reg(word, SH7751_PCICONF5);
        /* Set the values on window 1 PCI config registers */
        word =  PHYSADDR(map->window1.base);
-       outl(word, PCI_REG(SH7751_PCILAR1));
-       outl(word, PCI_REG(SH7751_PCICONF6));
+       pci_write_reg(word, SH4_PCILAR1);
+       pci_write_reg(word, SH7751_PCICONF6);
 
-       /* Set the local 16MB PCI memory space window to 
+       /* Set the local 16MB PCI memory space window to
         * the lowest PCI mapped address
         */
-       word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK;
-       PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word);
-       outl(word , PCI_REG(SH7751_PCIMBR));
+       word = PCIBIOS_MIN_MEM & SH4_PCIMBR_MASK;
+       pr_debug("PCI: Setting upper bits of Memory window to 0x%x\n", word);
+       pci_write_reg(word , SH4_PCIMBR);
 
        /* Map IO space into PCI IO window
         * The IO window is 64K-PCIBIOS_MIN_IO in size
-        * IO addresses will be translated to the 
+        * IO addresses will be translated to the
         * PCI IO window base address
         */
-       PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO,
-           (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO);
+       pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
+                PCIBIOS_MIN_IO, (64 << 10),
+                SH4_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*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO,0);
+       bigsur_port_map(PCIBIOS_MIN_IO, (64 << 10),
+                       SH4_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 & SH7751_PCIIOBR_MASK;
-       PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word);
-       outl(word, PCI_REG(SH7751_PCIIOBR));
-       
+       /* Make sure the MSB's of IO window are set to access PCI space
+        * correctly */
+       word = PCIBIOS_MIN_IO & SH4_PCIIOBR_MASK;
+       pr_debug("PCI: Setting upper bits of IO window to 0x%x\n", word);
+       pci_write_reg(word, SH4_PCIIOBR);
+
        /* Set PCI WCRx, BCRx's, copy from BSC locations */
 
        /* check BCR for SDRAM in specified area */
@@ -349,13 +190,13 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
 
        /* configure the wait control registers */
        word = inl(SH7751_WCR1);
-       outl(word, PCI_REG(SH7751_PCIWCR1));
+       pci_write_reg(word, SH4_PCIWCR1);
        word = inl(SH7751_WCR2);
-       outl(word, PCI_REG(SH7751_PCIWCR2));
+       pci_write_reg(word, SH4_PCIWCR2);
        word = inl(SH7751_WCR3);
-       outl(word, PCI_REG(SH7751_PCIWCR3));
+       pci_write_reg(word, SH4_PCIWCR3);
        word = inl(SH7751_MCR);
-       outl(word, PCI_REG(SH7751_PCIMCR));
+       pci_write_reg(word, SH4_PCIMCR);
 
        /* NOTE: I'm ignoring the PCI error IRQs for now..
         * TODO: add support for the internal error interrupts and
@@ -368,49 +209,8 @@ int __init sh7751_pcic_init(struct sh7751_pci_address_map *map)
 
        /* SH7751 init done, set central function init complete */
        /* use round robin mode to stop a device starving/overruning */
-       word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN | SH7751_PCICR_ARBM;
-       outl(word,PCI_REG(SH7751_PCICR)); 
+       word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_ARBM;
+       pci_write_reg(word, SH4_PCICR);
 
        return 1;
 }
-
-char * __init pcibios_setup(char *str)
-{
-       if (!strcmp(str, "off")) {
-               pci_probe = 0;
-               return NULL;
-       }
-
-       return str;
-}
-
-/* 
- *     IRQ functions 
- */
-static u8 __init sh7751_no_swizzle(struct pci_dev *dev, u8 *pin)
-{
-       /* no swizzling */
-       return PCI_SLOT(dev->devfn);
-}
-
-static int sh7751_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-       int irq = -1;
-
-       /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
-       irq = pcibios_map_platform_irq(slot,pin);
-       if( irq < 0 ) {
-               pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
-               return irq;
-       }
-
-       pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
-
-       return irq;
-}
-
-void __init pcibios_fixup_irqs(void)
-{
-       pci_fixup_irqs(sh7751_no_swizzle, sh7751_pci_lookup_irq);
-}
-
index 1fee5cae10d18c42005408103740cbfb10def672..68e3cb5e6bec2f5c7804c4b7cb3cff60235ae534 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Dustin McIntire (dustin@sensoria.com) (c) 2001
  *  Paul Mundt (lethal@linux-sh.org) (c) 2003
- *     
+ *
  *  May be copied or modified under the terms of the GNU General Public
  *  License.  See linux/COPYING for more information.
  *
 #ifndef _PCI_SH7751_H_
 #define _PCI_SH7751_H_
 
-#include <linux/pci.h>
-
-/* set debug level 4=verbose...1=terse */
-//#define DEBUG_PCI 3
-#undef DEBUG_PCI
-
-#ifdef DEBUG_PCI
-#define PCIDBG(n, x...) { if(DEBUG_PCI>=n) printk(x); }
-#else
-#define PCIDBG(n, x...)
-#endif
-
-/* startup values */
-#define PCI_PROBE_BIOS 1
-#define PCI_PROBE_CONF1 2
-#define PCI_PROBE_CONF2 4
-#define PCI_NO_SORT 0x100
-#define PCI_BIOS_SORT 0x200
-#define PCI_NO_CHECKS 0x400
-#define PCI_ASSIGN_ROMS 0x1000
-#define PCI_BIOS_IRQ_SCAN 0x2000
-
 /* Platform Specific Values */
 #define SH7751_VENDOR_ID             0x1054
 #define SH7751_DEVICE_ID             0x3505
   #define SH7751_PCICONF17_PMEN      0x00010000  /* PME Enable */
   #define SH7751_PCICONF17_PWST      0x00000003  /* Power State */
 /* SH7715 Internal PCI Registers */
-#define SH7751_PCICR               0x100         /* PCI Control Register */
-  #define SH7751_PCICR_PREFIX        0xA5000000  /* CR prefix for write */
-  #define SH7751_PCICR_TRSB          0x00000200  /* Target Read Single */
-  #define SH7751_PCICR_BSWP          0x00000100  /* Target Byte Swap */
-  #define SH7751_PCICR_PLUP          0x00000080  /* Enable PCI Pullup */
-  #define SH7751_PCICR_ARBM          0x00000040  /* PCI Arbitration Mode */
-  #define SH7751_PCICR_MD            0x00000030  /* MD9 and MD10 status */
-  #define SH7751_PCICR_SERR          0x00000008  /* SERR output assert */
-  #define SH7751_PCICR_INTA          0x00000004  /* INTA output assert */
-  #define SH7751_PCICR_PRST          0x00000002  /* PCI Reset Assert */
-  #define SH7751_PCICR_CFIN          0x00000001  /* Central Fun. Init Done */
-#define SH7751_PCILSR0             0x104         /* PCI Local Space Register0 */
-#define SH7751_PCILSR1             0x108         /* PCI Local Space Register1 */
-#define SH7751_PCILAR0             0x10C         /* PCI Local Address Register1 */
-#define SH7751_PCILAR1             0x110         /* PCI Local Address Register1 */
-#define SH7751_PCIINT              0x114         /* PCI Interrupt Register */
-  #define SH7751_PCIINT_MLCK         0x00008000  /* Master Lock Error */
-  #define SH7751_PCIINT_TABT         0x00004000  /* Target Abort Error */
-  #define SH7751_PCIINT_TRET         0x00000200  /* Target Retry Error */
-  #define SH7751_PCIINT_MFDE         0x00000100  /* Master Func. Disable Error */
-  #define SH7751_PCIINT_PRTY         0x00000080  /* Address Parity Error */
-  #define SH7751_PCIINT_SERR         0x00000040  /* SERR Detection Error */
-  #define SH7751_PCIINT_TWDP         0x00000020  /* Tgt. Write Parity Error */
-  #define SH7751_PCIINT_TRDP         0x00000010  /* Tgt. Read Parity Error Det. */
-  #define SH7751_PCIINT_MTABT        0x00000008  /* Master-Tgt. Abort Error */
-  #define SH7751_PCIINT_MMABT        0x00000004  /* Master-Master Abort Error */
-  #define SH7751_PCIINT_MWPD         0x00000002  /* Master Write PERR Detect */
-  #define SH7751_PCIINT_MRPD         0x00000002  /* Master Read PERR Detect */
-#define SH7751_PCIINTM             0x118         /* PCI Interrupt Mask Register */
-#define SH7751_PCIALR              0x11C         /* Error Address Register */
-#define SH7751_PCICLR              0x120         /* Error Command/Data Register */
-  #define SH7751_PCICLR_MPIO         0x80000000  /* Error Command/Data Register */
-  #define SH7751_PCICLR_MDMA0        0x40000000  /* DMA0 Transfer Error */
-  #define SH7751_PCICLR_MDMA1        0x20000000  /* DMA1 Transfer Error */
-  #define SH7751_PCICLR_MDMA2        0x10000000  /* DMA2 Transfer Error */
-  #define SH7751_PCICLR_MDMA3        0x08000000  /* DMA3 Transfer Error */
-  #define SH7751_PCICLR_TGT          0x04000000  /* Target Transfer Error */
-  #define SH7751_PCICLR_CMDL         0x0000000F  /* PCI Command at Error */
-#define SH7751_PCIAINT             0x130         /* Arbiter Interrupt Register */
-  #define SH7751_PCIAINT_MBKN        0x00002000  /* Master Broken Interrupt */
-  #define SH7751_PCIAINT_TBTO        0x00001000  /* Target Bus Time Out */
-  #define SH7751_PCIAINT_MBTO        0x00001000  /* Master Bus Time Out */
-  #define SH7751_PCIAINT_TABT        0x00000008  /* Target Abort */
-  #define SH7751_PCIAINT_MABT        0x00000004  /* Master Abort */
-  #define SH7751_PCIAINT_RDPE        0x00000002  /* Read Data Parity Error */
-  #define SH7751_PCIAINT_WDPE        0x00000002  /* Write Data Parity Error */
-#define SH7751_PCIAINTM            0x134         /* Arbiter Int. Mask Register */
-#define SH7751_PCIBMLR             0x138         /* Error Bus Master Register */
-  #define SH7751_PCIBMLR_REQ4        0x00000010  /* REQ4 bus master at error */
-  #define SH7751_PCIBMLR_REQ3        0x00000008  /* REQ3 bus master at error */
-  #define SH7751_PCIBMLR_REQ2        0x00000004  /* REQ2 bus master at error */
-  #define SH7751_PCIBMLR_REQ1        0x00000002  /* REQ1 bus master at error */
-  #define SH7751_PCIBMLR_REQ0        0x00000001  /* REQ0 bus master at error */
-#define SH7751_PCIDMABT            0x140         /* DMA Transfer Arb. Register */
-  #define SH7751_PCIDMABT_RRBN       0x00000001  /* DMA Arbitor Round-Robin */
-#define SH7751_PCIDPA0             0x180         /* DMA0 Transfer Addr. Register */
-#define SH7751_PCIDLA0             0x184         /* DMA0 Local Addr. Register */
-#define SH7751_PCIDTC0             0x188         /* DMA0 Transfer Cnt. Register */
-#define SH7751_PCIDCR0             0x18C         /* DMA0 Control Register */
-  #define SH7751_PCIDCR_ALGN         0x00000600  /* DMA Alignment Mode */
-  #define SH7751_PCIDCR_MAST         0x00000100  /* DMA Termination Type */
-  #define SH7751_PCIDCR_INTM         0x00000080  /* DMA Interrupt Done Mask*/
-  #define SH7751_PCIDCR_INTS         0x00000040  /* DMA Interrupt Done Status */
-  #define SH7751_PCIDCR_LHLD         0x00000020  /* Local Address Control */
-  #define SH7751_PCIDCR_PHLD         0x00000010  /* PCI Address Control*/
-  #define SH7751_PCIDCR_IOSEL        0x00000008  /* PCI Address Space Type */
-  #define SH7751_PCIDCR_DIR          0x00000004  /* DMA Transfer Direction */
-  #define SH7751_PCIDCR_STOP         0x00000002  /* Force DMA Stop */
-  #define SH7751_PCIDCR_STRT         0x00000001  /* DMA Start */
-#define SH7751_PCIDPA1             0x190         /* DMA1 Transfer Addr. Register */
-#define SH7751_PCIDLA1             0x194         /* DMA1 Local Addr. Register */
-#define SH7751_PCIDTC1             0x198         /* DMA1 Transfer Cnt. Register */
-#define SH7751_PCIDCR1             0x19C         /* DMA1 Control Register */
-#define SH7751_PCIDPA2             0x1A0         /* DMA2 Transfer Addr. Register */
-#define SH7751_PCIDLA2             0x1A4         /* DMA2 Local Addr. Register */
-#define SH7751_PCIDTC2             0x1A8         /* DMA2 Transfer Cnt. Register */
-#define SH7751_PCIDCR2             0x1AC         /* DMA2 Control Register */
-#define SH7751_PCIDPA3             0x1B0         /* DMA3 Transfer Addr. Register */
-#define SH7751_PCIDLA3             0x1B4         /* DMA3 Local Addr. Register */
-#define SH7751_PCIDTC3             0x1B8         /* DMA3 Transfer Cnt. Register */
-#define SH7751_PCIDCR3             0x1BC         /* DMA3 Control Register */
-#define SH7751_PCIPAR              0x1C0         /* PIO Address Register */
-  #define SH7751_PCIPAR_CFGEN        0x80000000  /* Configuration Enable */
-  #define SH7751_PCIPAR_BUSNO        0x00FF0000  /* Config. Bus Number */
-  #define SH7751_PCIPAR_DEVNO        0x0000FF00  /* Config. Device Number */
-  #define SH7751_PCIPAR_REGAD        0x000000FC  /* Register Address Number */
-#define SH7751_PCIMBR              0x1C4         /* Memory Base Address Register */
-  #define SH7751_PCIMBR_MASK         0xFF000000  /* Memory Space Mask */
-  #define SH7751_PCIMBR_LOCK         0x00000001  /* Lock Memory Space */
-#define SH7751_PCIIOBR             0x1C8         /* I/O Base Address Register */
-  #define SH7751_PCIIOBR_MASK         0xFFFC0000 /* IO Space Mask */
-  #define SH7751_PCIIOBR_LOCK         0x00000001 /* Lock IO Space */
-#define SH7751_PCIPINT             0x1CC         /* Power Mgmnt Int. Register */
-  #define SH7751_PCIPINT_D3           0x00000002 /* D3 Pwr Mgmt. Interrupt */
-  #define SH7751_PCIPINT_D0           0x00000001 /* D0 Pwr Mgmt. Interrupt */  
-#define SH7751_PCIPINTM            0x1D0         /* Power Mgmnt Mask Register */
-#define SH7751_PCICLKR             0x1D4         /* Clock Ctrl. Register */
-  #define SH7751_PCICLKR_PCSTP        0x00000002 /* PCI Clock Stop */
-  #define SH7751_PCICLKR_BCSTP        0x00000002 /* BCLK Clock Stop */
-/* For definitions of BCR, MCR see ... */
-#define SH7751_PCIBCR1             0x1E0         /* Memory BCR1 Register */
-#define SH7751_PCIBCR2             0x1E4         /* Memory BCR2 Register */
-#define SH7751_PCIWCR1             0x1E8         /* Wait Control 1 Register */
-#define SH7751_PCIWCR2             0x1EC         /* Wait Control 2 Register */
-#define SH7751_PCIWCR3             0x1F0         /* Wait Control 3 Register */
-#define SH7751_PCIMCR              0x1F4         /* Memory Control Register */
-#define SH7751_PCIBCR3            0x1f8         /* Memory BCR3 Register */
-#define SH7751_PCIPCTR             0x200         /* Port Control Register */
-  #define SH7751_PCIPCTR_P2EN        0x000400000 /* Port 2 Enable */
-  #define SH7751_PCIPCTR_P1EN        0x000200000 /* Port 1 Enable */
-  #define SH7751_PCIPCTR_P0EN        0x000100000 /* Port 0 Enable */
-  #define SH7751_PCIPCTR_P2UP        0x000000020 /* Port2 Pull Up Enable */
-  #define SH7751_PCIPCTR_P2IO        0x000000010 /* Port2 Output Enable */
-  #define SH7751_PCIPCTR_P1UP        0x000000008 /* Port1 Pull Up Enable */
-  #define SH7751_PCIPCTR_P1IO        0x000000004 /* Port1 Output Enable */
-  #define SH7751_PCIPCTR_P0UP        0x000000002 /* Port0 Pull Up Enable */
-  #define SH7751_PCIPCTR_P0IO        0x000000001 /* Port0 Output Enable */
-#define SH7751_PCIPDTR             0x204         /* Port Data Register */
-  #define SH7751_PCIPDTR_PB5         0x000000020 /* Port 5 Enable */
-  #define SH7751_PCIPDTR_PB4         0x000000010 /* Port 4 Enable */
-  #define SH7751_PCIPDTR_PB3         0x000000008 /* Port 3 Enable */
-  #define SH7751_PCIPDTR_PB2         0x000000004 /* Port 2 Enable */
-  #define SH7751_PCIPDTR_PB1         0x000000002 /* Port 1 Enable */
-  #define SH7751_PCIPDTR_PB0         0x000000001 /* Port 0 Enable */
-#define SH7751_PCIPDR              0x220         /* Port IO Data Register */
 
 /* Memory Control Registers */
 #define SH7751_BCR1                0xFF800000    /* Memory BCR1 Register */
 #define SH7751_CS5_BASE_ADDR       (SH7751_CS4_BASE_ADDR + SH7751_MEM_REGION_SIZE)
 #define SH7751_CS6_BASE_ADDR       (SH7751_CS5_BASE_ADDR + SH7751_MEM_REGION_SIZE)
 
-/* General PCI values */
-#define SH7751_PCI_HOST_BRIDGE         0x6
-
-/* Flags */
-#define SH7751_PCIC_NO_RESET   0x0001
-
-/* External functions defined per platform i.e. Big Sur, SE... (these could be routed 
- * through the machine vectors... */
-extern int pcibios_init_platform(void);
-extern int pcibios_map_platform_irq(u8 slot, u8 pin);
-
-struct sh7751_pci_address_space {
-       unsigned long base;
-       unsigned long size;
-};
-
-struct sh7751_pci_address_map {
-       struct sh7751_pci_address_space window0;
-       struct sh7751_pci_address_space window1;
-       unsigned long flags;
-};
+struct sh4_pci_address_map;
 
 /* arch/sh/drivers/pci/pci-sh7751.c */
-extern int sh7751_pcic_init(struct sh7751_pci_address_map *map);
+int sh7751_pcic_init(struct sh4_pci_address_map *map);
 
 #endif /* _PCI_SH7751_H_ */
-
diff --git a/arch/sh/drivers/pci/pci-sh7780.c b/arch/sh/drivers/pci/pci-sh7780.c
new file mode 100644 (file)
index 0000000..bd3064a
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ *     Low-Level PCI Support for the SH7780
+ *
+ *  Dustin McIntire (dustin@sensoria.com)
+ *     Derived from arch/i386/kernel/pci-*.c which bore the message:
+ *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
+ *
+ *  Ported to the new API by Paul Mundt <lethal@linux-sh.org>
+ *  With cleanup by Paul van Gool <pvangool@mimotech.com>
+ *
+ *  May be copied or modified under the terms of the GNU General Public
+ *  License.  See linux/COPYING for more information.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include "pci-sh4.h"
+
+/*
+ * Initialization. Try all known PCI access methods. Note that we support
+ * using both PCI BIOS and direct access: in such cases, we use I/O ports
+ * to access config space.
+ *
+ * Note that the platform specific initialization (BSC registers, and memory
+ * space mapping) will be called via the platform defined function
+ * pcibios_init_platform().
+ */
+static int __init sh7780_pci_init(void)
+{
+       unsigned int id;
+       int ret;
+
+       pr_debug("PCI: Starting intialization.\n");
+
+       outl(0x00000001, SH7780_PCI_VCR2); /* Enable PCIC */
+
+       /* check for SH7780/SH7780R hardware */
+       id = pci_read_reg(SH7780_PCIVID);
+       if ((id != ((SH7780_DEVICE_ID << 16) | SH7780_VENDOR_ID)) &&
+           (id != ((SH7781_DEVICE_ID << 16) | SH7780_VENDOR_ID))) {
+               printk(KERN_ERR "PCI: This is not an SH7780 (%x)\n", id);
+               return -ENODEV;
+       }
+
+       /* Setup the INTC */
+       ctrl_outl(0x00200000, INTC_ICR0);       /* INTC SH-4 Mode */
+       ctrl_outl(0x00078000, INTC_INT2MSKCR);  /* enable PCIINTA - PCIINTD */
+       ctrl_outl(0x40000000, INTC_INTMSK1);    /* disable IRL4-7 Interrupt */
+       ctrl_outl(0x0000fffe, INTC_INTMSK2);    /* disable IRL4-7 Interrupt */
+       ctrl_outl(0x80000000, INTC_INTMSKCLR1); /* enable IRL0-3 Interrupt */
+       ctrl_outl(0xfffe0000, INTC_INTMSKCLR2); /* enable IRL0-3 Interrupt */
+
+       if ((ret = sh4_pci_check_direct()) != 0)
+               return ret;
+
+       return pcibios_init_platform();
+}
+core_initcall(sh7780_pci_init);
+
+int __init sh7780_pcic_init(struct sh4_pci_address_map *map)
+{
+       u32 word;
+
+       /*
+        * This code is unused for some boards as it is done in the
+        * bootloader and doing it here means the MAC addresses loaded
+        * by the bootloader get lost.
+        */
+       if (!(map->flags & SH4_PCIC_NO_RESET)) {
+               /* toggle PCI reset pin */
+               word = SH4_PCICR_PREFIX | SH4_PCICR_PRST;
+               pci_write_reg(word, SH4_PCICR);
+               /* Wait for a long time... not 1 sec. but long enough */
+               mdelay(100);
+               word = SH4_PCICR_PREFIX;
+               pci_write_reg(word, SH4_PCICR);
+       }
+
+       /* set the command/status bits to:
+        * Wait Cycle Control + Parity Enable + Bus Master +
+        * Mem space enable
+        */
+       pci_write_reg(0x00000046, SH7780_PCICMD);
+
+       /* define this host as the host bridge */
+       word = PCI_BASE_CLASS_BRIDGE << 24;
+       pci_write_reg(word, SH7780_PCIRID);
+
+       /* Set IO and Mem windows to local address
+        * Make PCI and local address the same for easy 1 to 1 mapping
+        * Window0 = map->window0.size @ non-cached area base = SDRAM
+        * Window1 = map->window1.size @ cached area base = SDRAM
+        */
+       word = ((map->window0.size - 1) & 0x1ff00001) | 0x01;
+       pci_write_reg(0x07f00001, SH4_PCILSR0);
+       word = ((map->window1.size - 1) & 0x1ff00001) | 0x01;
+       pci_write_reg(0x00000001, SH4_PCILSR1);
+       /* Set the values on window 0 PCI config registers */
+       word = P2SEGADDR(map->window0.base);
+       pci_write_reg(0xa8000000, SH4_PCILAR0);
+       pci_write_reg(0x08000000, SH7780_PCIMBAR0);
+       /* Set the values on window 1 PCI config registers */
+       word = P2SEGADDR(map->window1.base);
+       pci_write_reg(0x00000000, SH4_PCILAR1);
+       pci_write_reg(0x00000000, SH7780_PCIMBAR1);
+
+       /* Map IO space into PCI IO window
+        * The IO window is 64K-PCIBIOS_MIN_IO in size
+        * IO addresses will be translated to the
+        * PCI IO window base address
+        */
+       pr_debug("PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n",
+                PCIBIOS_MIN_IO, (64 << 10),
+                SH7780_PCI_IO_BASE + PCIBIOS_MIN_IO);
+
+       /* NOTE: I'm ignoring the PCI error IRQs for now..
+        * TODO: add support for the internal error interrupts and
+        * DMA interrupts...
+        */
+
+#ifdef CONFIG_SH_R7780RP
+       pci_fixup_pcic();
+#endif
+
+       /* SH7780 init done, set central function init complete */
+       /* use round robin mode to stop a device starving/overruning */
+       word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO;
+       pci_write_reg(word, SH4_PCICR);
+
+       return 1;
+}
diff --git a/arch/sh/drivers/pci/pci-sh7780.h b/arch/sh/drivers/pci/pci-sh7780.h
new file mode 100644 (file)
index 0000000..f02d218
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *     Low-Level PCI Support for SH7780 targets
+ *
+ *  Dustin McIntire (dustin@sensoria.com) (c) 2001
+ *  Paul Mundt (lethal@linux-sh.org) (c) 2003
+ *
+ *  May be copied or modified under the terms of the GNU General Public
+ *  License.  See linux/COPYING for more information.
+ *
+ */
+
+#ifndef _PCI_SH7780_H_
+#define _PCI_SH7780_H_
+
+/* Platform Specific Values */
+#define SH7780_VENDOR_ID       0x1912
+#define SH7780_DEVICE_ID       0x0002
+#define SH7781_DEVICE_ID       0x0001
+
+/* SH7780 Control Registers */
+#define        SH7780_PCI_VCR0         0xFE000000
+#define        SH7780_PCI_VCR1         0xFE000004
+#define        SH7780_PCI_VCR2         0xFE000008
+
+/* SH7780 Specific Values */
+#define SH7780_PCI_CONFIG_BASE 0xFD000000      /* Config space base addr */
+#define SH7780_PCI_CONFIG_SIZE 0x01000000      /* Config space size */
+
+#define SH7780_PCI_MEMORY_BASE 0xFD000000      /* Memory space base addr */
+#define SH7780_PCI_MEM_SIZE    0x01000000      /* Size of Memory window */
+
+#define SH7780_PCI_IO_BASE     0xFE400000      /* IO space base address */
+#define SH7780_PCI_IO_SIZE     0x00400000      /* Size of IO window */
+
+#define SH7780_PCIREG_BASE     0xFE040000      /* PCI regs base address */
+#define PCI_REG(n)             (SH7780_PCIREG_BASE+n)
+
+/* SH7780 PCI Config Registers */
+#define SH7780_PCIVID          0x000           /* Vendor ID */
+#define SH7780_PCIDID          0x002           /* Device ID */
+#define SH7780_PCICMD          0x004           /* Command */
+#define SH7780_PCISTATUS       0x006           /* Status */
+#define SH7780_PCIRID          0x008           /* Revision ID */
+#define SH7780_PCIPIF          0x009           /* Program Interface */
+#define SH7780_PCISUB          0x00a           /* Sub class code */
+#define SH7780_PCIBCC          0x00b           /* Base class code */
+#define SH7780_PCICLS          0x00c           /* Cache line size */
+#define SH7780_PCILTM          0x00d           /* latency timer */
+#define SH7780_PCIHDR          0x00e           /* Header type */
+#define SH7780_PCIBIST         0x00f           /* BIST */
+#define SH7780_PCIIBAR         0x010           /* IO Base address */
+#define SH7780_PCIMBAR0                0x014           /* Memory base address0 */
+#define SH7780_PCIMBAR1                0x018           /* Memory base address1 */
+#define SH7780_PCISVID         0x02c           /* Sub system vendor ID */
+#define SH7780_PCISID          0x02e           /* Sub system ID */
+#define SH7780_PCICP           0x034
+#define SH7780_PCIINTLINE      0x03c           /* Interrupt line */
+#define SH7780_PCIINTPIN       0x03d           /* Interrupt pin */
+#define SH7780_PCIMINGNT       0x03e           /* Minumum grand */
+#define SH7780_PCIMAXLAT       0x03f           /* Maxmum latency */
+#define SH7780_PCICID          0x040
+#define SH7780_PCINIP          0x041
+#define SH7780_PCIPMC          0x042
+#define SH7780_PCIPMCSR                0x044
+#define SH7780_PCIPMCSR_BSE    0x046
+#define SH7780_PCICDD          0x047
+
+#define SH7780_PCIMBR0         0x1E0
+#define SH7780_PCIMBMR0                0x1E4
+#define SH7780_PCIMBR2         0x1F0
+#define SH7780_PCIMBMR2                0x1F4
+#define SH7780_PCIIOBR         0x1F8
+#define SH7780_PCIIOBMR                0x1FC
+#define SH7780_PCICSCR0                0x210           /* Cache Snoop1 Cnt. Register */
+#define SH7780_PCICSCR1                0x214           /* Cache Snoop2 Cnt. Register */
+#define SH7780_PCICSAR0                0x218   /* Cache Snoop1 Addr. Register */
+#define SH7780_PCICSAR1                0x21C   /* Cache Snoop2 Addr. Register */
+
+/* General Memory Config Addresses */
+#define SH7780_CS0_BASE_ADDR   0x0
+#define SH7780_MEM_REGION_SIZE 0x04000000
+#define SH7780_CS1_BASE_ADDR   (SH7780_CS0_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS2_BASE_ADDR   (SH7780_CS1_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS3_BASE_ADDR   (SH7780_CS2_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS4_BASE_ADDR   (SH7780_CS3_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS5_BASE_ADDR   (SH7780_CS4_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+#define SH7780_CS6_BASE_ADDR   (SH7780_CS5_BASE_ADDR + SH7780_MEM_REGION_SIZE)
+
+struct sh4_pci_address_map;
+
+/* arch/sh/drivers/pci/pci-sh7780.c */
+int sh7780_pcic_init(struct sh4_pci_address_map *map);
+
+#endif /* _PCI_SH7780_H_ */
index 7c81b8b65bb505cbcaf58fad69364ee148cbc434..4ab5ea6b35fb5eeaf22fa5dd5889803f4d9555c1 100644 (file)
 static void pci_set_rbar_region(unsigned int region,     unsigned long localAddr,
                         unsigned long pciOffset, unsigned long regionSize);
 
-/*
- * The pcibios_map_platform_irq function is defined in the appropriate
- * board specific code and referenced here
- */
-extern int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
-
 static __init void SetPCIPLL(void)
 {
        {
@@ -422,13 +416,6 @@ struct pci_ops st40pci_config_ops = {
 /* Everything hangs off this */
 static struct pci_bus *pci_root_bus;
 
-
-static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
-{
-       return PCI_SLOT(dev->devfn);
-}
-
-
 static int __init pcibios_init(void)
 {
        extern unsigned long memory_start, memory_end;
@@ -465,17 +452,11 @@ static int __init pcibios_init(void)
        /* ok, do the scan man */
        pci_root_bus = pci_scan_bus(0, &st40pci_config_ops, NULL);
        pci_assign_unassigned_resources();
-       pci_fixup_irqs(no_swizzle, pcibios_map_platform_irq);
 
        return 0;
 }
-
 subsys_initcall(pcibios_init);
 
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
-}
-
 /*
  * Publish a region of local address space over the PCI bus
  * to other devices.
index 3d546ba329cfb866a9457751f6ab888523b867cd..d439336d2e18258c1a19865c529b12a59fb78544 100644 (file)
@@ -1,21 +1,45 @@
-/* arch/sh/kernel/pci.c
- * $Id: pci.c,v 1.1 2003/08/24 19:15:45 lethal Exp $
+/*
+ * arch/sh/drivers/pci/pci.c
  *
  * Copyright (c) 2002 M. R. Brown  <mrbrown@linux-sh.org>
- * 
- * 
+ * Copyright (c) 2004 - 2006 Paul Mundt  <lethal@linux-sh.org>
+ *
  * These functions are collected here to reduce duplication of common
  * code amongst the many platform-specific PCI support code files.
- * 
+ *
  * These routines require the following board-specific routines:
  * void pcibios_fixup_irqs();
  *
  * See include/asm-sh/pci.h for more information.
+ *
+ * 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/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <asm/io.h>
+
+static inline u8 bridge_swizzle(u8 pin, u8 slot)
+{
+       return (((pin - 1) + slot) % 4) + 1;
+}
+
+static u8 __init simple_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+       u8 pin = *pinp;
+
+       while (dev->bus->parent) {
+               pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+               /* Move up the chain of bridges. */
+               dev = dev->bus->self;
+       }
+       *pinp = pin;
+
+       /* The slot is the slot of the last bridge. */
+       return PCI_SLOT(dev->devfn);
+}
 
 static int __init pcibios_init(void)
 {
@@ -26,26 +50,32 @@ static int __init pcibios_init(void)
 #ifdef CONFIG_PCI_AUTO
        /* assign resources */
        busno = 0;
-       for (p = board_pci_channels; p->pci_ops != NULL; p++) {
+       for (p = board_pci_channels; p->pci_ops != NULL; p++)
                busno = pciauto_assign_resources(busno, p) + 1;
-       }
 #endif
 
        /* scan the buses */
        busno = 0;
-       for (p= board_pci_channels; p->pci_ops != NULL; p++) {
+       for (p = board_pci_channels; p->pci_ops != NULL; p++) {
                bus = pci_scan_bus(busno, p->pci_ops, p);
-               busno = bus->subordinate+1;
+               busno = bus->subordinate + 1;
        }
 
-       /* board-specific fixups */
-       pcibios_fixup_irqs();
+       pci_fixup_irqs(simple_swizzle, pcibios_map_platform_irq);
 
        return 0;
 }
-
 subsys_initcall(pcibios_init);
 
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+       pci_read_bridge_bases(bus);
+}
+
 void
 pcibios_update_resource(struct pci_dev *dev, struct resource *root,
                        struct resource *res, int resource)
@@ -61,13 +91,17 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root,
                new |= PCI_ROM_ADDRESS_ENABLE;
                reg = dev->rom_base_reg;
        } else {
-               /* Somebody might have asked allocation of a non-standard resource */
+               /*
+                * Somebody might have asked allocation of a non-standard
+                * resource
+                */
                return;
        }
-       
+
        pci_write_config_dword(dev, reg, new);
        pci_read_config_dword(dev, reg, &check);
-       if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+       if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ?
+               PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
                printk(KERN_ERR "PCI: Error while updating region "
                       "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
                       new, check);
@@ -145,7 +179,8 @@ void pcibios_set_master(struct pci_dev *dev)
                lat = pcibios_max_latency;
        else
                return;
-       printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
+       printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n",
+              pci_name(dev), lat);
        pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
 }
 
@@ -153,3 +188,39 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
 {
        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+       unsigned long start = pci_resource_start(dev, bar);
+       unsigned long len = pci_resource_len(dev, bar);
+       unsigned long flags = pci_resource_flags(dev, bar);
+
+       if (unlikely(!len || !start))
+               return NULL;
+       if (maxlen && len > maxlen)
+               len = maxlen;
+
+       /*
+        * Presently the IORESOURCE_MEM case is a bit special, most
+        * SH7751 style PCI controllers have PCI memory at a fixed
+        * location in the address space where no remapping is desired
+        * (typically at 0xfd000000, but is_pci_memaddr() will know
+        * best). With the IORESOURCE_MEM case more care has to be taken
+        * to inhibit page table mapping for legacy cores, but this is
+        * punted off to __ioremap().
+        *                                      -- PFM.
+        */
+       if (flags & IORESOURCE_IO)
+               return ioport_map(start, len);
+       if (flags & IORESOURCE_MEM)
+               return ioremap(start, len);
+
+       return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+       iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
index f05cd96f8867a5647b0adace1e3141bc1b38e405..5da88a43d350f4d38d92956090f4dce201e17d6e 100644 (file)
@@ -6,9 +6,10 @@ extra-y        := head.o init_task.o vmlinux.lds
 
 obj-y  := process.o signal.o entry.o traps.o irq.o \
        ptrace.o setup.o time.o sys_sh.o semaphore.o \
-       io.o io_generic.o sh_ksyms.o
+       io.o io_generic.o sh_ksyms.o syscalls.o
 
 obj-y                          += cpu/ timers/
+obj-$(CONFIG_VSYSCALL)         += vsyscall/
 
 obj-$(CONFIG_SMP)              += smp.o
 obj-$(CONFIG_CF_ENABLER)       += cf-enabler.o
@@ -18,3 +19,5 @@ obj-$(CONFIG_SH_CPU_FREQ)     += cpufreq.o
 obj-$(CONFIG_MODULES)          += module.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o
+obj-$(CONFIG_APM)              += apm.o
+obj-$(CONFIG_PM)               += pm.o
diff --git a/arch/sh/kernel/apm.c b/arch/sh/kernel/apm.c
new file mode 100644 (file)
index 0000000..871e7d6
--- /dev/null
@@ -0,0 +1,539 @@
+/*
+ * bios-less APM driver for hp680
+ *
+ * Copyright 2005 (c) Andriy Skulysh <askulysh@gmail.com>
+ *
+ * based on ARM APM driver by
+ *  Jamey Hicks <jamey@crl.dec.com>
+ *
+ * adapted from the APM BIOS driver for Linux by
+ *  Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * APM 1.2 Reference:
+ *   Intel Corporation, Microsoft Corporation. Advanced Power Management
+ *   (APM) BIOS Interface Specification, Revision 1.2, February 1996.
+ *
+ * [This document is available from Microsoft at:
+ *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/apm_bios.h>
+#include <linux/pm.h>
+#include <linux/pm_legacy.h>
+#include <asm/apm.h>
+
+#define MODNAME "apm"
+
+/*
+ * The apm_bios device is one of the misc char devices.
+ * This is its minor number.
+ */
+#define APM_MINOR_DEV                  134
+
+/*
+ * Maximum number of events stored
+ */
+#define APM_MAX_EVENTS                 16
+
+struct apm_queue {
+       unsigned int            event_head;
+       unsigned int            event_tail;
+       apm_event_t             events[APM_MAX_EVENTS];
+};
+
+/*
+ * The per-file APM data
+ */
+struct apm_user {
+       struct list_head        list;
+
+       unsigned int            suser: 1;
+       unsigned int            writer: 1;
+       unsigned int            reader: 1;
+
+       int                     suspend_result;
+       unsigned int            suspend_state;
+#define SUSPEND_NONE   0               /* no suspend pending */
+#define SUSPEND_PENDING        1               /* suspend pending read */
+#define SUSPEND_READ   2               /* suspend read, pending ack */
+#define SUSPEND_ACKED  3               /* suspend acked */
+#define SUSPEND_DONE   4               /* suspend completed */
+
+       struct apm_queue        queue;
+};
+
+/*
+ * Local variables
+ */
+static int suspends_pending;
+
+static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
+static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
+
+/*
+ * This is a list of everyone who has opened /dev/apm_bios
+ */
+static DECLARE_RWSEM(user_list_lock);
+static LIST_HEAD(apm_user_list);
+
+/*
+ * kapmd info.  kapmd provides us a process context to handle
+ * "APM" events within - specifically necessary if we're going
+ * to be suspending the system.
+ */
+static DECLARE_WAIT_QUEUE_HEAD(kapmd_wait);
+static DECLARE_COMPLETION(kapmd_exit);
+static DEFINE_SPINLOCK(kapmd_queue_lock);
+static struct apm_queue kapmd_queue;
+
+int apm_suspended;
+EXPORT_SYMBOL(apm_suspended);
+
+/* Platform-specific apm_read_proc(). */
+int (*apm_get_info)(char *buf, char **start, off_t fpos, int length);
+EXPORT_SYMBOL(apm_get_info);
+
+/*
+ * APM event queue management.
+ */
+static inline int queue_empty(struct apm_queue *q)
+{
+       return q->event_head == q->event_tail;
+}
+
+static inline apm_event_t queue_get_event(struct apm_queue *q)
+{
+       q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+       return q->events[q->event_tail];
+}
+
+static void queue_add_event(struct apm_queue *q, apm_event_t event)
+{
+       q->event_head = (q->event_head + 1) % APM_MAX_EVENTS;
+       if (q->event_head == q->event_tail) {
+               static int notified;
+
+               if (notified++ == 0)
+                       printk(KERN_ERR "apm: an event queue overflowed\n");
+
+               q->event_tail = (q->event_tail + 1) % APM_MAX_EVENTS;
+       }
+       q->events[q->event_head] = event;
+}
+
+static void queue_event_one_user(struct apm_user *as, apm_event_t event)
+{
+       if (as->suser && as->writer) {
+               switch (event) {
+               case APM_SYS_SUSPEND:
+               case APM_USER_SUSPEND:
+                       /*
+                        * If this user already has a suspend pending,
+                        * don't queue another one.
+                        */
+                       if (as->suspend_state != SUSPEND_NONE)
+                               return;
+
+                       as->suspend_state = SUSPEND_PENDING;
+                       suspends_pending++;
+                       break;
+               }
+       }
+       queue_add_event(&as->queue, event);
+}
+
+static void queue_event(apm_event_t event, struct apm_user *sender)
+{
+       struct apm_user *as;
+
+       down_read(&user_list_lock);
+
+       list_for_each_entry(as, &apm_user_list, list)
+               if (as != sender && as->reader)
+                       queue_event_one_user(as, event);
+
+       up_read(&user_list_lock);
+       wake_up_interruptible(&apm_waitqueue);
+}
+
+/**
+ * apm_queue_event - queue an APM event for kapmd
+ * @event: APM event
+ *
+ * Queue an APM event for kapmd to process and ultimately take the
+ * appropriate action.  Only a subset of events are handled:
+ *   %APM_LOW_BATTERY
+ *   %APM_POWER_STATUS_CHANGE
+ *   %APM_USER_SUSPEND
+ *   %APM_SYS_SUSPEND
+ *   %APM_CRITICAL_SUSPEND
+ */
+void apm_queue_event(apm_event_t event)
+{
+       spin_lock_irq(&kapmd_queue_lock);
+       queue_add_event(&kapmd_queue, event);
+       spin_unlock_irq(&kapmd_queue_lock);
+
+       wake_up_interruptible(&kapmd_wait);
+}
+EXPORT_SYMBOL(apm_queue_event);
+
+static void apm_suspend(void)
+{
+       struct apm_user *as;
+       int err;
+
+       apm_suspended = 1;
+       err = pm_suspend(PM_SUSPEND_MEM);
+
+       /*
+        * Anyone on the APM queues will think we're still suspended.
+        * Send a message so everyone knows we're now awake again.
+        */
+       queue_event(APM_NORMAL_RESUME, NULL);
+
+       /*
+        * Finally, wake up anyone who is sleeping on the suspend.
+        */
+       down_read(&user_list_lock);
+       list_for_each_entry(as, &apm_user_list, list) {
+               as->suspend_result = err;
+               as->suspend_state = SUSPEND_DONE;
+       }
+       up_read(&user_list_lock);
+
+       wake_up(&apm_suspend_waitqueue);
+       apm_suspended = 0;
+}
+
+static ssize_t apm_read(struct file *fp, char __user *buf,
+                       size_t count, loff_t *ppos)
+{
+       struct apm_user *as = fp->private_data;
+       apm_event_t event;
+       int i = count, ret = 0;
+
+       if (count < sizeof(apm_event_t))
+               return -EINVAL;
+
+       if (queue_empty(&as->queue) && fp->f_flags & O_NONBLOCK)
+               return -EAGAIN;
+
+       wait_event_interruptible(apm_waitqueue, !queue_empty(&as->queue));
+
+       while ((i >= sizeof(event)) && !queue_empty(&as->queue)) {
+               event = queue_get_event(&as->queue);
+
+               ret = -EFAULT;
+               if (copy_to_user(buf, &event, sizeof(event)))
+                       break;
+
+               if (event == APM_SYS_SUSPEND || event == APM_USER_SUSPEND)
+                       as->suspend_state = SUSPEND_READ;
+
+               buf += sizeof(event);
+               i -= sizeof(event);
+       }
+
+       if (i < count)
+               ret = count - i;
+
+       return ret;
+}
+
+static unsigned int apm_poll(struct file *fp, poll_table * wait)
+{
+       struct apm_user *as = fp->private_data;
+
+       poll_wait(fp, &apm_waitqueue, wait);
+       return queue_empty(&as->queue) ? 0 : POLLIN | POLLRDNORM;
+}
+
+/*
+ * apm_ioctl - handle APM ioctl
+ *
+ * APM_IOC_SUSPEND
+ *   This IOCTL is overloaded, and performs two functions.  It is used to:
+ *     - initiate a suspend
+ *     - acknowledge a suspend read from /dev/apm_bios.
+ *   Only when everyone who has opened /dev/apm_bios with write permission
+ *   has acknowledge does the actual suspend happen.
+ */
+static int
+apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg)
+{
+       struct apm_user *as = filp->private_data;
+       unsigned long flags;
+       int err = -EINVAL;
+
+       if (!as->suser || !as->writer)
+               return -EPERM;
+
+       switch (cmd) {
+       case APM_IOC_SUSPEND:
+               as->suspend_result = -EINTR;
+
+               if (as->suspend_state == SUSPEND_READ) {
+                       /*
+                        * If we read a suspend command from /dev/apm_bios,
+                        * then the corresponding APM_IOC_SUSPEND ioctl is
+                        * interpreted as an acknowledge.
+                        */
+                       as->suspend_state = SUSPEND_ACKED;
+                       suspends_pending--;
+               } else {
+                       /*
+                        * Otherwise it is a request to suspend the system.
+                        * Queue an event for all readers, and expect an
+                        * acknowledge from all writers who haven't already
+                        * acknowledged.
+                        */
+                       queue_event(APM_USER_SUSPEND, as);
+               }
+
+               /*
+                * If there are no further acknowledges required, suspend
+                * the system.
+                */
+               if (suspends_pending == 0)
+                       apm_suspend();
+
+               /*
+                * Wait for the suspend/resume to complete.  If there are
+                * pending acknowledges, we wait here for them.
+                *
+                * Note that we need to ensure that the PM subsystem does
+                * not kick us out of the wait when it suspends the threads.
+                */
+               flags = current->flags;
+               current->flags |= PF_NOFREEZE;
+
+               /*
+                * Note: do not allow a thread which is acking the suspend
+                * to escape until the resume is complete.
+                */
+               if (as->suspend_state == SUSPEND_ACKED)
+                       wait_event(apm_suspend_waitqueue,
+                                        as->suspend_state == SUSPEND_DONE);
+               else
+                       wait_event_interruptible(apm_suspend_waitqueue,
+                                        as->suspend_state == SUSPEND_DONE);
+
+               current->flags = flags;
+               err = as->suspend_result;
+               as->suspend_state = SUSPEND_NONE;
+               break;
+       }
+
+       return err;
+}
+
+static int apm_release(struct inode * inode, struct file * filp)
+{
+       struct apm_user *as = filp->private_data;
+       filp->private_data = NULL;
+
+       down_write(&user_list_lock);
+       list_del(&as->list);
+       up_write(&user_list_lock);
+
+       /*
+        * We are now unhooked from the chain.  As far as new
+        * events are concerned, we no longer exist.  However, we
+        * need to balance suspends_pending, which means the
+        * possibility of sleeping.
+        */
+       if (as->suspend_state != SUSPEND_NONE) {
+               suspends_pending -= 1;
+               if (suspends_pending == 0)
+                       apm_suspend();
+       }
+
+       kfree(as);
+       return 0;
+}
+
+static int apm_open(struct inode * inode, struct file * filp)
+{
+       struct apm_user *as;
+
+       as = kzalloc(sizeof(*as), GFP_KERNEL);
+       if (as) {
+               /*
+                * XXX - this is a tiny bit broken, when we consider BSD
+                * process accounting. If the device is opened by root, we
+                * instantly flag that we used superuser privs. Who knows,
+                * we might close the device immediately without doing a
+                * privileged operation -- cevans
+                */
+               as->suser = capable(CAP_SYS_ADMIN);
+               as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
+               as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+
+               down_write(&user_list_lock);
+               list_add(&as->list, &apm_user_list);
+               up_write(&user_list_lock);
+
+               filp->private_data = as;
+       }
+
+       return as ? 0 : -ENOMEM;
+}
+
+static struct file_operations apm_bios_fops = {
+       .owner          = THIS_MODULE,
+       .read           = apm_read,
+       .poll           = apm_poll,
+       .ioctl          = apm_ioctl,
+       .open           = apm_open,
+       .release        = apm_release,
+};
+
+static struct miscdevice apm_device = {
+       .minor          = APM_MINOR_DEV,
+       .name           = "apm_bios",
+       .fops           = &apm_bios_fops
+};
+
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Arguments, with symbols from linux/apm_bios.h.
+ *
+ *   0) Linux driver version (this will change if format changes)
+ *   1) APM BIOS Version.  Usually 1.0, 1.1 or 1.2.
+ *   2) APM flags from APM Installation Check (0x00):
+ *     bit 0: APM_16_BIT_SUPPORT
+ *     bit 1: APM_32_BIT_SUPPORT
+ *     bit 2: APM_IDLE_SLOWS_CLOCK
+ *     bit 3: APM_BIOS_DISABLED
+ *     bit 4: APM_BIOS_DISENGAGED
+ *   3) AC line status
+ *     0x00: Off-line
+ *     0x01: On-line
+ *     0x02: On backup power (BIOS >= 1.1 only)
+ *     0xff: Unknown
+ *   4) Battery status
+ *     0x00: High
+ *     0x01: Low
+ *     0x02: Critical
+ *     0x03: Charging
+ *     0x04: Selected battery not present (BIOS >= 1.2 only)
+ *     0xff: Unknown
+ *   5) Battery flag
+ *     bit 0: High
+ *     bit 1: Low
+ *     bit 2: Critical
+ *     bit 3: Charging
+ *     bit 7: No system battery
+ *     0xff: Unknown
+ *   6) Remaining battery life (percentage of charge):
+ *     0-100: valid
+ *     -1: Unknown
+ *   7) Remaining battery life (time units):
+ *     Number of remaining minutes or seconds
+ *     -1: Unknown
+ *   8) min = minutes; sec = seconds
+ */
+static int apm_read_proc(char *buf, char **start, off_t fpos, int length)
+{
+       if (likely(apm_get_info))
+               return apm_get_info(buf, start, fpos, length);
+
+       return -EINVAL;
+}
+#endif
+
+static int kapmd(void *arg)
+{
+       daemonize("kapmd");
+       current->flags |= PF_NOFREEZE;
+
+       do {
+               apm_event_t event;
+
+               wait_event_interruptible(kapmd_wait,
+                               !queue_empty(&kapmd_queue) || !pm_active);
+
+               if (!pm_active)
+                       break;
+
+               spin_lock_irq(&kapmd_queue_lock);
+               event = 0;
+               if (!queue_empty(&kapmd_queue))
+                       event = queue_get_event(&kapmd_queue);
+               spin_unlock_irq(&kapmd_queue_lock);
+
+               switch (event) {
+               case 0:
+                       break;
+
+               case APM_LOW_BATTERY:
+               case APM_POWER_STATUS_CHANGE:
+                       queue_event(event, NULL);
+                       break;
+
+               case APM_USER_SUSPEND:
+               case APM_SYS_SUSPEND:
+                       queue_event(event, NULL);
+                       if (suspends_pending == 0)
+                               apm_suspend();
+                       break;
+
+               case APM_CRITICAL_SUSPEND:
+                       apm_suspend();
+                       break;
+               }
+       } while (1);
+
+       complete_and_exit(&kapmd_exit, 0);
+}
+
+static int __init apm_init(void)
+{
+       int ret;
+
+       pm_active = 1;
+
+       ret = kernel_thread(kapmd, NULL, CLONE_KERNEL);
+       if (unlikely(ret < 0)) {
+               pm_active = 0;
+               return ret;
+       }
+
+       create_proc_info_entry("apm", 0, NULL, apm_read_proc);
+
+       ret = misc_register(&apm_device);
+       if (unlikely(ret != 0)) {
+               remove_proc_entry("apm", NULL);
+
+               pm_active = 0;
+               wake_up(&kapmd_wait);
+               wait_for_completion(&kapmd_exit);
+       }
+
+       return ret;
+}
+
+static void __exit apm_exit(void)
+{
+       misc_deregister(&apm_device);
+       remove_proc_entry("apm", NULL);
+
+       pm_active = 0;
+       wake_up(&kapmd_wait);
+       wait_for_completion(&kapmd_exit);
+}
+
+module_init(apm_init);
+module_exit(apm_exit);
+
+MODULE_AUTHOR("Stephen Rothwell, Andriy Skulysh");
+MODULE_DESCRIPTION("Advanced Power Management");
+MODULE_LICENSE("GPL");
index f1f9ab87f0b0fb3025bd7fe71690a7f0a809c0dd..3e5fa1e24df097b450c5a33dd035d94cd04f2d09 100644 (file)
@@ -10,7 +10,8 @@
  */
 
 #include <linux/init.h>
-
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
@@ -32,8 +33,6 @@
 /* SH4 can't access PCMCIA interface through P2 area.
  * we must remap it with appropreate attribute bit of the page set.
  * this part is based on Greg Banks' hd64465_ss.c implementation - Masahiro Abe */
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
 
 #if defined(CONFIG_CF_AREA6)
 #define slot_no 0
@@ -41,9 +40,6 @@
 #define slot_no 1
 #endif
 
-/* defined in mm/ioremap.c */
-extern void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags);
-
 /* use this pointer to access to directly connected compact flash io area*/
 void *cf_io_base;
 
@@ -62,7 +58,7 @@ static int __init allocate_cf_area(void)
                return -ENOMEM;
        }
 /*     printk("p3_ioremap(paddr=0x%08lx, psize=0x%08lx, prot=0x%08lx)=0x%08lx\n",
-               paddrbase, psize, prot.pgprot, cf_io_base);*/
+               paddrbase, psize, prot.pgprot, cf_io_base);*/
 
        /* XXX : do we need attribute and common-memory area also? */
 
@@ -87,7 +83,7 @@ static int __init cf_init_default(void)
 }
 
 #if defined(CONFIG_SH_SOLUTION_ENGINE)
-#include <asm/se/se.h>
+#include <asm/se.h>
 
 /*
  * SolutionEngine
index 59d5b748752fee2f271889b9150923d276763249..fb5dac0693827df8316d15ec253b7005c0349b39 100644 (file)
@@ -8,6 +8,5 @@ obj-$(CONFIG_CPU_SH2)           += sh2/
 obj-$(CONFIG_CPU_SH3)          += sh3/
 obj-$(CONFIG_CPU_SH4)          += sh4/
 
-obj-$(CONFIG_SH_RTC)           += rtc.o
 obj-$(CONFIG_UBC_WAKEUP)       += ubc.o
 obj-$(CONFIG_SH_ADC)           += adc.o
index 97fa37f42b841e2bcaabbef4e07a933fad0fb73b..51ec64cdf348ebb30c61ffab7be21e4dc2ffa1d6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/sh/kernel/cpu/clock.c - SuperH clock framework
  *
- *  Copyright (C) 2005  Paul Mundt
+ *  Copyright (C) 2005, 2006  Paul Mundt
  *
  * This clock framework is derived from the OMAP version by:
  *
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/kref.h>
 #include <linux/seq_file.h>
@@ -24,7 +25,7 @@
 
 static LIST_HEAD(clock_list);
 static DEFINE_SPINLOCK(clock_lock);
-static DECLARE_MUTEX(clock_list_sem);
+static DEFINE_MUTEX(clock_list_sem);
 
 /*
  * Each subtype is expected to define the init routines for these clocks,
@@ -140,21 +141,21 @@ void clk_disable(struct clk *clk)
 
 int clk_register(struct clk *clk)
 {
-       down(&clock_list_sem);
+       mutex_lock(&clock_list_sem);
 
        list_add(&clk->node, &clock_list);
        kref_init(&clk->kref);
 
-       up(&clock_list_sem);
+       mutex_unlock(&clock_list_sem);
 
        return 0;
 }
 
 void clk_unregister(struct clk *clk)
 {
-       down(&clock_list_sem);
+       mutex_lock(&clock_list_sem);
        list_del(&clk->node);
-       up(&clock_list_sem);
+       mutex_unlock(&clock_list_sem);
 }
 
 inline unsigned long clk_get_rate(struct clk *clk)
@@ -198,14 +199,14 @@ struct clk *clk_get(const char *id)
 {
        struct clk *p, *clk = ERR_PTR(-ENOENT);
 
-       down(&clock_list_sem);
+       mutex_lock(&clock_list_sem);
        list_for_each_entry(p, &clock_list, node) {
                if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
                        clk = p;
                        break;
                }
        }
-       up(&clock_list_sem);
+       mutex_unlock(&clock_list_sem);
 
        return clk;
 }
@@ -225,7 +226,7 @@ int __init clk_init(void)
 {
        int i, ret = 0;
 
-       BUG_ON(unlikely(!master_clk.rate));
+       BUG_ON(!master_clk.rate);
 
        for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) {
                struct clk *clk = onchip_clocks[i];
index 868e68b288809a406fe01801d50c87f393ec9cf4..bfb90eb0b7a6caabc529f33e49c5371a74f62208 100644 (file)
@@ -4,6 +4,7 @@
  * CPU init code
  *
  * Copyright (C) 2002, 2003  Paul Mundt
+ * Copyright (C) 2003  Richard Curnow
  *
  * 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
@@ -13,6 +14,7 @@
 #include <linux/kernel.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
+#include <asm/page.h>
 #include <asm/system.h>
 #include <asm/cacheflush.h>
 #include <asm/cache.h>
@@ -51,7 +53,15 @@ static void __init cache_init(void)
        ccr = ctrl_inl(CCR);
 
        /*
-        * If the cache is already enabled .. flush it.
+        * At this point we don't know whether the cache is enabled or not - a
+        * bootloader may have enabled it.  There are at least 2 things that
+        * could be dirty in the cache at this point:
+        * 1. kernel command line set up by boot loader
+        * 2. spilled registers from the prolog of this function
+        * => before re-initialising the cache, we must do a purge of the whole
+        * cache out to memory for safety.  As long as nothing is spilled
+        * during the loop to lines that have already been done, this is safe.
+        * - RPC
         */
        if (ccr & CCR_CACHE_ENABLE) {
                unsigned long ways, waysize, addrstart;
@@ -98,6 +108,8 @@ static void __init cache_init(void)
        /* Force EMODE if possible */
        if (cpu_data->dcache.ways > 1)
                flags |= CCR_CACHE_EMODE;
+       else
+               flags &= ~CCR_CACHE_EMODE;
 #endif
 
 #ifdef CONFIG_SH_WRITETHROUGH
@@ -112,6 +124,9 @@ static void __init cache_init(void)
        /* Turn on OCRAM -- halve the OC */
        flags |= CCR_CACHE_ORA;
        cpu_data->dcache.sets >>= 1;
+
+       cpu_data->dcache.way_size = cpu_data->dcache.sets *
+                                   cpu_data->dcache.linesz;
 #endif
 
        ctrl_outl(flags, CCR);
@@ -184,6 +199,10 @@ asmlinkage void __init sh_cpu_init(void)
        /* Init the cache */
        cache_init();
 
+       shm_align_mask = max_t(unsigned long,
+                              cpu_data->dcache.way_size - 1,
+                              PAGE_SIZE - 1);
+
        /* Disable the FPU */
        if (fpu_disabled) {
                printk("FPU Disabled\n");
index e3cccea15e1d1dd670792f92314dc463efeb2f66..1c034c283f594aee3b73ac546909dfb173bfbd17 100644 (file)
@@ -3,5 +3,6 @@
 #
 obj-y  += ipr.o imask.o
 
-obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o
-obj-$(CONFIG_CPU_HAS_INTC2_IRQ)        += intc2.o
+obj-$(CONFIG_CPU_HAS_PINT_IRQ)         += pint.o
+obj-$(CONFIG_CPU_HAS_MASKREG_IRQ)      += maskreg.o
+obj-$(CONFIG_CPU_HAS_INTC2_IRQ)                += intc2.o
index 30064bf6e154bf5f46a2f5c0cfea97bf50c616d4..e30e4b7aa70e739be7ed77211b32d5cc04f1801f 100644 (file)
@@ -241,9 +241,9 @@ static struct intc2_init {
        /* 110-111 reserved/unused */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
        { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2},
-#ifdef CONFIG_SH_RTC
-       { RTC_IRQ, 4, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
-#endif
+       { 21, 1, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY },
+       { 22, 1, 1, 0, INTC_RTC_MSK, TIMER_PRIORITY },
+       { 23, 1, 2, 0, INTC_RTC_MSK, TIMER_PRIORITY },
        { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
        { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
        { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY },
index 0f545941fb4fdbcd2444f1a085c36da650108db1..f785822cd5dea4fb32e908a93f328c00ec3ffa4d 100644 (file)
@@ -57,31 +57,27 @@ static struct hw_interrupt_type ipr_irq_type = {
 
 static void disable_ipr_irq(unsigned int irq)
 {
-       unsigned long val, flags;
+       unsigned long val;
        unsigned int addr = ipr_data[irq].addr;
        unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift);
 
        /* Set the priority in IPR to 0 */
-       local_irq_save(flags);
        val = ctrl_inw(addr);
        val &= mask;
        ctrl_outw(val, addr);
-       local_irq_restore(flags);
 }
 
 static void enable_ipr_irq(unsigned int irq)
 {
-       unsigned long val, flags;
+       unsigned long val;
        unsigned int addr = ipr_data[irq].addr;
        int priority = ipr_data[irq].priority;
        unsigned short value = (priority << ipr_data[irq].shift);
 
        /* Set priority in IPR back to original value */
-       local_irq_save(flags);
        val = ctrl_inw(addr);
        val |= value;
        ctrl_outw(val, addr);
-       local_irq_restore(flags);
 }
 
 static void mask_and_ack_ipr(unsigned int irq)
@@ -89,6 +85,7 @@ static void mask_and_ack_ipr(unsigned int irq)
        disable_ipr_irq(irq);
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7706) || \
     defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
        /* This is needed when we use edge triggered setting */
        /* XXX: Is it really needed? */
@@ -123,7 +120,7 @@ void __init init_IRQ(void)
 #ifndef CONFIG_CPU_SUBTYPE_SH7780
        make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
        make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY);
-#if defined(CONFIG_SH_RTC)
+#ifdef RTC_IRQ
        make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
 #endif
 
@@ -162,6 +159,7 @@ void __init init_IRQ(void)
 #endif
 
 #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7706) || \
     defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
        /*
         * Initialize the Interrupt Controller (INTC)
@@ -192,6 +190,8 @@ void __init init_IRQ(void)
        /* Perform the machine specific initialisation */
        if (sh_mv.mv_init_irq != NULL)
                sh_mv.mv_init_irq();
+
+       irq_ctx_init(smp_processor_id());
 }
 
 #if !defined(CONFIG_CPU_HAS_PINT_IRQ)
similarity index 63%
rename from arch/sh/boards/adx/irq_maskreg.c
rename to arch/sh/kernel/cpu/irq/maskreg.c
index 4b2abe5eb165e53664bb290c37b0e5aca2b2a70a..492db31b3cab6278c848c85b2ae28706ffabbd8c 100644 (file)
@@ -1,30 +1,23 @@
 /*
- * linux/arch/sh/kernel/irq_maskreg.c
+ * Interrupt handling for Simple external interrupt mask register
  *
  * Copyright (C) 2001 A&D Co., Ltd. <http://www.aandd.co.jp>
  *
- * This file may be copied or modified under the terms of the GNU
- * General Public License.  See linux/COPYING for more information.
- *
- * Interrupt handling for Simple external interrupt mask register
- *
  * This is for the machine which have single 16 bit register
  * for masking external IRQ individually.
- * Each bit of the register is for masking each interrupt.  
+ * Each bit of the register is for masking each interrupt.
+ *
+ * This file may be copied or modified under the terms of the GNU
+ * General Public License.  See linux/COPYING for more information.
  */
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irq.h>
-
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/machvec.h>
 
-/* address of external interrupt mask register
- * address must be set prior to use these (maybe in init_XXX_irq())
- * XXX : is it better to use .config than specifying it in code? */
-unsigned short *irq_mask_register = 0;
+/* address of external interrupt mask register */
+unsigned long irq_mask_register;
 
 /* forward declaration */
 static unsigned int startup_maskreg_irq(unsigned int irq);
@@ -36,7 +29,7 @@ static void end_maskreg_irq(unsigned int irq);
 
 /* hw_interrupt_type */
 static struct hw_interrupt_type maskreg_irq_type = {
-       .typename = " Mask Register",
+       .typename = "Mask Register",
        .startup = startup_maskreg_irq,
        .shutdown = shutdown_maskreg_irq,
        .enable = enable_maskreg_irq,
@@ -47,7 +40,7 @@ static struct hw_interrupt_type maskreg_irq_type = {
 
 /* actual implementatin */
 static unsigned int startup_maskreg_irq(unsigned int irq)
-{ 
+{
        enable_maskreg_irq(irq);
        return 0; /* never anything pending */
 }
@@ -59,32 +52,26 @@ static void shutdown_maskreg_irq(unsigned int irq)
 
 static void disable_maskreg_irq(unsigned int irq)
 {
-       if (irq_mask_register) {
-               unsigned long flags;
-               unsigned short val, mask = 0x01 << irq;
+       unsigned short val, mask = 0x01 << irq;
+
+       BUG_ON(!irq_mask_register);
 
-               /* Set "irq"th bit */
-               local_irq_save(flags);
-               val = ctrl_inw((unsigned long)irq_mask_register);
-               val |= mask;
-               ctrl_outw(val, (unsigned long)irq_mask_register);
-               local_irq_restore(flags);
-       }
+       /* Set "irq"th bit */
+       val = ctrl_inw(irq_mask_register);
+       val |= mask;
+       ctrl_outw(val, irq_mask_register);
 }
 
 static void enable_maskreg_irq(unsigned int irq)
 {
-       if (irq_mask_register) {
-               unsigned long flags;
-               unsigned short val, mask = ~(0x01 << irq);
+       unsigned short val, mask = ~(0x01 << irq);
+
+       BUG_ON(!irq_mask_register);
 
-               /* Clear "irq"th bit */
-               local_irq_save(flags);
-               val = ctrl_inw((unsigned long)irq_mask_register);
-               val &= mask;
-               ctrl_outw(val, (unsigned long)irq_mask_register);
-               local_irq_restore(flags);
-       }
+       /* Clear "irq"th bit */
+       val = ctrl_inw(irq_mask_register);
+       val &= mask;
+       ctrl_outw(val, irq_mask_register);
 }
 
 static void mask_and_ack_maskreg(unsigned int irq)
@@ -101,6 +88,6 @@ static void end_maskreg_irq(unsigned int irq)
 void make_maskreg_irq(unsigned int irq)
 {
        disable_irq_nosync(irq);
-       irq_desc[irq].chip = &maskreg_irq_type;
+       irq_desc[irq].handler = &maskreg_irq_type;
        disable_maskreg_irq(irq);
 }
index 80cd8108d36aca86a86e45da2decc7418b620135..17f47b373d6ed2cb0ea49bfb8f05f0f5a799e9d8 100644 (file)
@@ -48,26 +48,22 @@ static struct hw_interrupt_type pint_irq_type = {
 
 static void disable_pint_irq(unsigned int irq)
 {
-       unsigned long val, flags;
+       unsigned long val;
 
-       local_irq_save(flags);
        val = ctrl_inw(INTC_INTER);
        val &= ~(1 << (irq - PINT_IRQ_BASE));
        ctrl_outw(val, INTC_INTER);     /* disable PINTn */
        portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2);
-       local_irq_restore(flags);
 }
 
 static void enable_pint_irq(unsigned int irq)
 {
-       unsigned long val, flags;
+       unsigned long val;
 
-       local_irq_save(flags);
        val = ctrl_inw(INTC_INTER);
        val |= 1 << (irq - PINT_IRQ_BASE);
        ctrl_outw(val, INTC_INTER);     /* enable PINTn */
        portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2;
-       local_irq_restore(flags);
 }
 
 static void mask_and_ack_pint(unsigned int irq)
diff --git a/arch/sh/kernel/cpu/rtc.c b/arch/sh/kernel/cpu/rtc.c
deleted file mode 100644 (file)
index 4304cf7..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * linux/arch/sh/kernel/rtc.c -- SH3 / SH4 on-chip RTC support
- *
- *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
- *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/time.h>
-#include <linux/bcd.h>
-#include <asm/io.h>
-#include <asm/rtc.h>
-
-void sh_rtc_gettimeofday(struct timespec *ts)
-{
-       unsigned int sec128, sec, sec2, min, hr, wk, day, mon, yr, yr100, cf_bit;
-       unsigned long flags;
-
- again:
-       do {
-               local_irq_save(flags);
-               ctrl_outb(0, RCR1);  /* Clear CF-bit */
-               sec128 = ctrl_inb(R64CNT);
-               sec = ctrl_inb(RSECCNT);
-               min = ctrl_inb(RMINCNT);
-               hr  = ctrl_inb(RHRCNT);
-               wk  = ctrl_inb(RWKCNT);
-               day = ctrl_inb(RDAYCNT);
-               mon = ctrl_inb(RMONCNT);
-#if defined(CONFIG_CPU_SH4)
-               yr  = ctrl_inw(RYRCNT);
-               yr100 = (yr >> 8);
-               yr &= 0xff;
-#else
-               yr  = ctrl_inb(RYRCNT);
-               yr100 = (yr == 0x99) ? 0x19 : 0x20;
-#endif
-               sec2 = ctrl_inb(R64CNT);
-               cf_bit = ctrl_inb(RCR1) & RCR1_CF;
-               local_irq_restore(flags);
-       } while (cf_bit != 0 || ((sec128 ^ sec2) & RTC_BIT_INVERTED) != 0);
-
-       BCD_TO_BIN(yr100);
-       BCD_TO_BIN(yr);
-       BCD_TO_BIN(mon);
-       BCD_TO_BIN(day);
-       BCD_TO_BIN(hr);
-       BCD_TO_BIN(min);
-       BCD_TO_BIN(sec);
-
-       if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 ||
-           hr > 23 || min > 59 || sec > 59) {
-               printk(KERN_ERR
-                      "SH RTC: invalid value, resetting to 1 Jan 2000\n");
-               local_irq_save(flags);
-               ctrl_outb(RCR2_RESET, RCR2);  /* Reset & Stop */
-               ctrl_outb(0, RSECCNT);
-               ctrl_outb(0, RMINCNT);
-               ctrl_outb(0, RHRCNT);
-               ctrl_outb(6, RWKCNT);
-               ctrl_outb(1, RDAYCNT);
-               ctrl_outb(1, RMONCNT);
-#if defined(CONFIG_CPU_SH4)
-               ctrl_outw(0x2000, RYRCNT);
-#else
-               ctrl_outb(0, RYRCNT);
-#endif
-               ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2);  /* Start */
-               goto again;
-       }
-
-#if RTC_BIT_INVERTED != 0
-       if ((sec128 & RTC_BIT_INVERTED))
-               sec--;
-#endif
-
-       ts->tv_sec = mktime(yr100 * 100 + yr, mon, day, hr, min, sec);
-       ts->tv_nsec = ((sec128 * 1000000) / 128) * 1000;
-}
-
-/*
- * Changed to only care about tv_sec, and not the full timespec struct
- * (i.e. tv_nsec).  It can easily be switched to timespec for future cpus
- * that support setting usec or nsec RTC values.
- */
-int sh_rtc_settimeofday(const time_t secs)
-{
-       int retval = 0;
-       int real_seconds, real_minutes, cmos_minutes;
-       unsigned long flags;
-
-       local_irq_save(flags);
-       ctrl_outb(RCR2_RESET, RCR2);  /* Reset pre-scaler & stop RTC */
-
-       cmos_minutes = ctrl_inb(RMINCNT);
-       BCD_TO_BIN(cmos_minutes);
-
-       /*
-        * since we're only adjusting minutes and seconds,
-        * don't interfere with hour overflow. This avoids
-        * messing with unknown time zones but requires your
-        * RTC not to be off by more than 15 minutes
-        */
-       real_seconds = secs % 60;
-       real_minutes = secs / 60;
-       if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
-               real_minutes += 30;     /* correct for half hour time zone */
-       real_minutes %= 60;
-
-       if (abs(real_minutes - cmos_minutes) < 30) {
-               BIN_TO_BCD(real_seconds);
-               BIN_TO_BCD(real_minutes);
-               ctrl_outb(real_seconds, RSECCNT);
-               ctrl_outb(real_minutes, RMINCNT);
-       } else {
-               printk(KERN_WARNING
-                      "set_rtc_time: can't update from %d to %d\n",
-                      cmos_minutes, real_minutes);
-               retval = -1;
-       }
-
-       ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2);  /* Start RTC */
-       local_irq_restore(flags);
-
-       return retval;
-}
index b54dbb9a0c8612232bf14b003dee3ec0c23c21f6..58d3815695ffa70d21f15f4243461223b0b70064 100644 (file)
@@ -4,10 +4,21 @@
 
 obj-y  := ex.o probe.o
 
+# CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7705)       += setup-sh7705.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7706)       += setup-sh7709.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7707)       += setup-sh7709.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7708)       += setup-sh7708.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7709)       += setup-sh7709.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7300)       += setup-sh7300.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7710)       += setup-sh7710.o
+
+# Primary on-chip clocks (common)
 clock-$(CONFIG_CPU_SH3)                        := clock-sh3.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7300)     := clock-sh7300.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7705)     := clock-sh7705.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7706)     := clock-sh7706.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7709)     := clock-sh7709.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7710)     := clock-sh7300.o
 
 obj-y  += $(clock-y)
-
diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7706.c b/arch/sh/kernel/cpu/sh3/clock-sh7706.c
new file mode 100644 (file)
index 0000000..0cf96f9
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * arch/sh/kernel/cpu/sh3/clock-sh7706.c
+ *
+ * SH7706 support for the clock framework
+ *
+ *  Copyright (C) 2006  Takashi YOSHII
+ *
+ * Based on arch/sh/kernel/cpu/sh3/clock-sh7709.c
+ *  Copyright (C) 2005  Andriy Skulysh
+ *
+ * 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/kernel.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+
+static int stc_multipliers[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
+static int ifc_divisors[]    = { 1, 2, 4, 1, 3, 1, 1, 1 };
+static int pfc_divisors[]    = { 1, 2, 4, 1, 3, 6, 1, 1 };
+
+static void master_clk_init(struct clk *clk)
+{
+       int frqcr = ctrl_inw(FRQCR);
+       int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
+
+       clk->rate *= pfc_divisors[idx];
+}
+
+static struct clk_ops sh7706_master_clk_ops = {
+       .init           = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+       int frqcr = ctrl_inw(FRQCR);
+       int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003);
+
+       clk->rate = clk->parent->rate / pfc_divisors[idx];
+}
+
+static struct clk_ops sh7706_module_clk_ops = {
+       .recalc         = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+       int frqcr = ctrl_inw(FRQCR);
+       int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4);
+
+       clk->rate = clk->parent->rate / stc_multipliers[idx];
+}
+
+static struct clk_ops sh7706_bus_clk_ops = {
+       .recalc         = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+       int frqcr = ctrl_inw(FRQCR);
+       int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2);
+
+       clk->rate = clk->parent->rate / ifc_divisors[idx];
+}
+
+static struct clk_ops sh7706_cpu_clk_ops = {
+       .recalc         = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7706_clk_ops[] = {
+       &sh7706_master_clk_ops,
+       &sh7706_module_clk_ops,
+       &sh7706_bus_clk_ops,
+       &sh7706_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+       if (idx < ARRAY_SIZE(sh7706_clk_ops))
+               *ops = sh7706_clk_ops[idx];
+}
index cc04e9e239ffb13e7c0b4cea5b362d71a5541829..44daf44833f90852e0f39557784fab51e2fc8ae2 100644 (file)
@@ -84,8 +84,12 @@ ENTRY(interrupt_table)
        .long   do_IRQ  !      rovi
        .long   do_IRQ                  
        .long   do_IRQ                  /* 5E0 */
-#if  defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
-     defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+#if  defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+     defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+     defined(CONFIG_CPU_SUBTYPE_SH7706) || \
+     defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+     defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+     defined(CONFIG_CPU_SUBTYPE_SH7710)
        .long   do_IRQ  ! 32 IRQ  irq0  /* 600 */
        .long   do_IRQ  ! 33      irq1
        .long   do_IRQ  ! 34      irq2
@@ -147,6 +151,51 @@ ENTRY(interrupt_table)
        .long   do_IRQ  ! 62 PCC  pcc0i
        .long   do_IRQ  ! 63      pcc1i /* 9E0 */
 #endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+       .long   exception_none  ! 61    /* 9A0 */
+       .long   exception_none  ! 62
+       .long   exception_none  ! 63
+       .long   exception_none  ! 64    /* A00 */
+       .long   exception_none  ! 65
+       .long   exception_none  ! 66
+       .long   exception_none  ! 67
+       .long   exception_none  ! 68
+       .long   exception_none  ! 69
+       .long   exception_none  ! 70
+       .long   exception_none  ! 71
+       .long   exception_none  ! 72    /* B00 */
+       .long   exception_none  ! 73
+       .long   exception_none  ! 74
+       .long   exception_none  ! 75
+       .long   do_IRQ  ! 76 DMAC2 dei4 /* B80 */
+       .long   do_IRQ  ! 77 DMAC2 dei5
+       .long   exception_none  ! 78
+       .long   do_IRQ  ! 79 IPSEC ipseci /* BE0 */
+       .long   do_IRQ  ! 80 EDMAC eint0 /* C00 */
+       .long   do_IRQ  ! 81 EDMAC eint1
+       .long   do_IRQ  ! 82 EDMAC eint2
+       .long   exception_none  ! 83    /* C60 */
+       .long   exception_none  ! 84
+       .long   exception_none  ! 85
+       .long   exception_none  ! 86
+       .long   exception_none  ! 87
+       .long   exception_none  ! 88    /* D00 */
+       .long   exception_none  ! 89
+       .long   exception_none  ! 90
+       .long   exception_none  ! 91
+       .long   exception_none  ! 92
+       .long   exception_none  ! 93
+       .long   exception_none  ! 94
+       .long   exception_none  ! 95
+       .long   do_IRQ  ! 96 SIOF eri0  /* E00 */
+       .long   do_IRQ  ! 97      txi0
+       .long   do_IRQ  ! 98      rxi0
+       .long   do_IRQ  ! 99      cci0
+       .long   do_IRQ  ! 100     eri1  /* E80 */
+       .long   do_IRQ  ! 101     txi1
+       .long   do_IRQ  ! 102     rxi2
+       .long   do_IRQ  ! 103     cci3
+#endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7300)
        .long   do_IRQ  ! 64
        .long   do_IRQ  ! 65
@@ -195,4 +244,3 @@ ENTRY(interrupt_table)
        .long   do_IRQ  ! 108
 #endif
 #endif
-
index 5cdc8863860120b7e77e9444e75960f98fd340c0..e67098836290ea9ff583991fe0a6e05c27876175 100644 (file)
@@ -72,6 +72,12 @@ int __init detect_cpu_and_cache_system(void)
                cpu_data->dcache.sets           = 256;
                cpu_data->type = CPU_SH7729;
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7706)
+               cpu_data->type = CPU_SH7706;
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+               cpu_data->type = CPU_SH7710;
+#endif
 #if defined(CONFIG_CPU_SUBTYPE_SH7705)
                cpu_data->type = CPU_SH7705;
 
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7300.c b/arch/sh/kernel/cpu/sh3/setup-sh7300.c
new file mode 100644 (file)
index 0000000..ab4d204
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH7300 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xa4430000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCI,
+               .irqs           = { 80, 80, 80, 80 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7300_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7300_devices_setup(void)
+{
+       return platform_add_devices(sh7300_devices,
+                                   ARRAY_SIZE(sh7300_devices));
+}
+__initcall(sh7300_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c
new file mode 100644 (file)
index 0000000..a8e41c5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SH7705 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xa4400000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 52, 53, 55, 54 },
+       }, {
+               .mapbase        = 0xa4410000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 56, 57, 59, 58 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7705_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7705_devices_setup(void)
+{
+       return platform_add_devices(sh7705_devices,
+                                   ARRAY_SIZE(sh7705_devices));
+}
+__initcall(sh7705_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7708.c b/arch/sh/kernel/cpu/sh3/setup-sh7708.c
new file mode 100644 (file)
index 0000000..f933723
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH7708 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xfffffe80,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCI,
+               .irqs           = { 23, 24, 25, 0 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7708_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7708_devices_setup(void)
+{
+       return platform_add_devices(sh7708_devices,
+                                   ARRAY_SIZE(sh7708_devices));
+}
+__initcall(sh7708_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7709.c b/arch/sh/kernel/cpu/sh3/setup-sh7709.c
new file mode 100644 (file)
index 0000000..ff43ef2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SH7707/SH7709 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xfffffe80,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCI,
+               .irqs           = { 23, 24, 25, 0 },
+       }, {
+               .mapbase        = 0xa4000150,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 56, 57, 59, 58 },
+       }, {
+               .mapbase        = 0xa4000140,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_IRDA,
+               .irqs           = { 52, 53, 55, 54 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7709_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7709_devices_setup(void)
+{
+       return platform_add_devices(sh7709_devices,
+                                   ARRAY_SIZE(sh7709_devices));
+}
+__initcall(sh7709_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c
new file mode 100644 (file)
index 0000000..895f99e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH7710 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xa4400000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 52, 53, 55, 54 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7710_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7710_devices_setup(void)
+{
+       return platform_add_devices(sh7710_devices,
+                                   ARRAY_SIZE(sh7710_devices));
+}
+__initcall(sh7710_devices_setup);
index 3d5cafc71ae307d8c9c2abc6c730a889436b8ffb..8dbf3895ece7406c248e2405f8bc18b2392f0f81 100644 (file)
@@ -7,6 +7,16 @@ obj-y  := ex.o probe.o
 obj-$(CONFIG_SH_FPU)                    += fpu.o
 obj-$(CONFIG_SH_STORE_QUEUES)          += sq.o
 
+# CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7750)       += setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751)       += setup-sh7750.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7760)       += setup-sh7760.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7770)       += setup-sh7770.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780)       += setup-sh7780.o
+obj-$(CONFIG_CPU_SUBTYPE_SH73180)      += setup-sh73180.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7343)       += setup-sh7343.o
+obj-$(CONFIG_CPU_SUBTYPE_SH4_202)      += setup-sh4-202.o
+
 # Primary on-chip clocks (common)
 clock-$(CONFIG_CPU_SH4)                        := clock-sh4.o
 clock-$(CONFIG_CPU_SUBTYPE_SH73180)    := clock-sh73180.o
index 26a27df0650509c127f3339cd90a821365ca2b62..7146893a6cca5c3ebf33b78565eb2144c2f2f188 100644 (file)
@@ -72,6 +72,7 @@ ENTRY(interrupt_table)
        .long   do_IRQ  ! 1110
        .long   exception_error         
        ! Internal hardware
+#ifndef CONFIG_CPU_SUBTYPE_SH7780
        .long   do_IRQ  ! TMU0 tuni0    /* 400 */
        .long   do_IRQ  ! TMU1 tuni1
        .long   do_IRQ  ! TMU2 tuni2
@@ -122,6 +123,13 @@ ENTRY(interrupt_table)
        .long   do_IRQ  ! 45      dmte5
        .long   do_IRQ  ! 46      dmte6
        .long   do_IRQ  ! 47      dmte7         /* 7E0 */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
+       .long   do_IRQ  ! 44 IIC1 ali           /* 780 */
+       .long   do_IRQ  ! 45      tacki
+       .long   do_IRQ  ! 46      waiti
+       .long   do_IRQ  ! 47      dtei          /* 7E0 */
+       .long   do_IRQ  ! 48 DMAC dei0          /* 800 */
+       .long   do_IRQ  ! 49      dei1          /* 820 */
 #else
        .long   exception_error                 ! 44    /* 780 */
        .long   exception_error                 ! 45
@@ -131,7 +139,8 @@ ENTRY(interrupt_table)
 #if defined(CONFIG_SH_FPU)
        .long   do_fpu_state_restore    ! 48    /* 800 */
        .long   do_fpu_state_restore    ! 49    /* 820 */
-#else
+#elif !defined(CONFIG_CPU_SUBTYPE_SH7343) && \
+      !defined(CONFIG_CPU_SUBTYPE_SH73180)
        .long   exception_error
        .long   exception_error
 #endif
@@ -224,7 +233,7 @@ ENTRY(interrupt_table)
        .long   exception_error
        .long   do_IRQ  ! ADC   adi
        .long   do_IRQ  ! CMT   cmti    /* FA0 */
-#elif defined(CONFIG_CPU_SUBTYPE_SH73180)
+#elif defined(CONFIG_CPU_SUBTYPE_SH73180) || defined(CONFIG_CPU_SUBTYPE_SH7343)
        .long   do_IRQ  !  50 0x840
        .long   do_IRQ  !  51 0x860
        .long   do_IRQ  !  52 0x880
@@ -379,5 +388,168 @@ ENTRY(interrupt_table)
        .long   exception_error                 ! 141 0x13a0
        .long   exception_error                 ! 142 0x13c0
        .long   exception_error                 ! 143 0x13e0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
+       .long   do_IRQ  !  50 0x840
+       .long   do_IRQ  !  51 0x860
+       .long   do_IRQ  !  52 0x880
+       .long   do_IRQ  !  53 0x8a0
+       .long   do_IRQ  !  54 0x8c0
+       .long   do_IRQ  !  55 0x8e0
+       .long   do_IRQ  !  56 0x900
+       .long   do_IRQ  !  57 0x920
+       .long   do_IRQ  !  58 0x940
+       .long   do_IRQ  !  59 0x960
+       .long   do_IRQ  !  60 0x980
+       .long   do_IRQ  !  61 0x9a0
+       .long   do_IRQ  !  62 0x9c0
+       .long   do_IRQ  !  63 0x9e0
+       .long   do_IRQ  !  64 0xa00
+       .long   do_IRQ  !  65 0xa20
+       .long   do_IRQ  !  66 0xa4d
+       .long   do_IRQ  !  67 0xa60
+       .long   do_IRQ  !  68 0xa80
+       .long   do_IRQ  !  69 0xaa0
+       .long   do_IRQ  !  70 0xac0
+       .long   do_IRQ  !  71 0xae0
+       .long   do_IRQ  !  72 0xb00
+       .long   do_IRQ  !  73 0xb20
+       .long   do_IRQ  !  74 0xb40
+       .long   do_IRQ  !  75 0xb60
+       .long   do_IRQ  !  76 0xb80
+       .long   do_IRQ  !  77 0xba0
+       .long   do_IRQ  !  78 0xbc0
+       .long   do_IRQ  !  79 0xbe0
+       .long   do_IRQ  !  80 0xc00
+       .long   do_IRQ  !  81 0xc20
+       .long   do_IRQ  !  82 0xc40
+       .long   do_IRQ  !  83 0xc60
+       .long   do_IRQ  !  84 0xc80
+       .long   do_IRQ  !  85 0xca0
+       .long   do_IRQ  !  86 0xcc0
+       .long   do_IRQ  !  87 0xce0
+       .long   do_IRQ  !  88 0xd00
+       .long   do_IRQ  !  89 0xd20
+       .long   do_IRQ  !  90 0xd40
+       .long   do_IRQ  !  91 0xd60
+       .long   do_IRQ  !  92 0xd80
+       .long   do_IRQ  !  93 0xda0
+       .long   do_IRQ  !  94 0xdc0
+       .long   do_IRQ  !  95 0xde0
+       .long   do_IRQ  !  96 0xe00
+       .long   do_IRQ  !  97 0xe20
+       .long   do_IRQ  !  98 0xe40
+       .long   do_IRQ  !  99 0xe60
+       .long   do_IRQ  ! 100 0xe80
+       .long   do_IRQ  ! 101 0xea0
+       .long   do_IRQ  ! 102 0xec0
+       .long   do_IRQ  ! 103 0xee0
+       .long   do_IRQ  ! 104 0xf00
+       .long   do_IRQ  ! 105 0xf20
+       .long   do_IRQ  ! 106 0xf40
+       .long   do_IRQ  ! 107 0xf60
+       .long   do_IRQ  ! 108 0xf80
+#endif
+#else
+       .long   exception_error         /* 400 */
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! RTC   ati
+       .long   do_IRQ  !       pri
+       .long   do_IRQ  !       cui
+       .long   exception_error
+       .long   exception_error         /* 500 */
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! WDT   iti     /* 560 */
+       .long   do_IRQ  ! TMU-ch0
+       .long   do_IRQ  ! TMU-ch1
+       .long   do_IRQ  ! TMU-ch2
+       .long   do_IRQ  ! ticpi2        /* 5E0 */
+       .long   do_IRQ  ! 32 Hitachi UDI        /* 600 */
+       .long   exception_error
+       .long   do_IRQ  ! 34 DMAC dmte0
+       .long   do_IRQ  ! 35      dmte1
+       .long   do_IRQ  ! 36      dmte2
+       .long   do_IRQ  ! 37      dmte3
+       .long   do_IRQ  ! 38      dmae
+       .long   exception_error                 ! 39    /* 6E0 */
+       .long   do_IRQ  ! 40 SCIF-ch0 eri               /* 700 */
+       .long   do_IRQ  ! 41          rxi
+       .long   do_IRQ  ! 42          bri
+       .long   do_IRQ  ! 43          txi
+       .long   do_IRQ  ! 44 DMAC dmte4         /* 780 */
+       .long   do_IRQ  ! 45      dmte5
+       .long   do_IRQ  ! 46      dmte6
+       .long   do_IRQ  ! 47      dmte7         /* 7E0 */
+#if defined(CONFIG_SH_FPU)
+       .long   do_fpu_state_restore    ! 48    /* 800 */
+       .long   do_fpu_state_restore    ! 49    /* 820 */
+#else
+       .long   exception_error
+       .long   exception_error
+#endif
+       .long   exception_error                 /* 840 */
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! 56 CMT        /* 900 */
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! 60 HAC
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! PCI serr      /* A00 */
+       .long   do_IRQ  !     INTA
+       .long   do_IRQ  !     INTB
+       .long   do_IRQ  !     INTC
+       .long   do_IRQ  !     INTD
+       .long   do_IRQ  !     err
+       .long   do_IRQ  !     pwd3
+       .long   do_IRQ  !     pwd2
+       .long   do_IRQ  !     pwd1      /* B00 */
+       .long   do_IRQ  !     pwd0
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! SCIF-ch1 eri  /* B80 */
+       .long   do_IRQ  !          rxi
+       .long   do_IRQ  !          bri
+       .long   do_IRQ  !          txi
+       .long   do_IRQ  ! SIOF          /* C00 */
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! HSPI          /* C80 */
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! MMCIF fatat   /* D00 */
+       .long   do_IRQ  !       tran
+       .long   do_IRQ  !       err
+       .long   do_IRQ  !       frdy
+       .long   do_IRQ  ! DMAC dmint8   /* D80 */
+       .long   do_IRQ  !      dmint9
+       .long   do_IRQ  !      dmint10
+       .long   do_IRQ  !      dmint11
+       .long   do_IRQ  ! TMU-ch3       /* E00 */
+       .long   do_IRQ  ! TMU-ch4
+       .long   do_IRQ  ! TMU-ch5
+       .long   exception_error
+       .long   do_IRQ  ! SSI
+       .long   exception_error
+       .long   exception_error
+       .long   exception_error
+       .long   do_IRQ  ! FLCTL flste   /* F00 */
+       .long   do_IRQ  !       fltend
+       .long   do_IRQ  !       fltrq0
+       .long   do_IRQ  !       fltrq1
+       .long   do_IRQ  ! GPIO gpioi0   /* F80 */
+       .long   do_IRQ  !      gpioi1
+       .long   do_IRQ  !      gpioi2
+       .long   do_IRQ  !      gpioi3
 #endif
 
index 42427b79697bfca67abd57c3358463f8a9363f5b..c294de1e14a3c2ae8d994e25a7f238fcbce9b8b6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * CPU Subtype Probing for SH-4.
  *
- * Copyright (C) 2001, 2002, 2003, 2004  Paul Mundt
+ * Copyright (C) 2001 - 2006  Paul Mundt
  * Copyright (C) 2003  Richard Curnow
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -29,7 +29,7 @@ int __init detect_cpu_and_cache_system(void)
                [9] = (1 << 16)
        };
 
-       pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff;
+       pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffffff;
        prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff;
        cvr = (ctrl_inl(CCN_CVR));
 
@@ -38,7 +38,6 @@ int __init detect_cpu_and_cache_system(void)
         */
        cpu_data->icache.way_incr       = (1 << 13);
        cpu_data->icache.entry_shift    = 5;
-       cpu_data->icache.entry_mask     = 0x1fe0;
        cpu_data->icache.sets           = 256;
        cpu_data->icache.ways           = 1;
        cpu_data->icache.linesz         = L1_CACHE_BYTES;
@@ -48,13 +47,29 @@ int __init detect_cpu_and_cache_system(void)
         */
        cpu_data->dcache.way_incr       = (1 << 14);
        cpu_data->dcache.entry_shift    = 5;
-       cpu_data->dcache.entry_mask     = 0x3fe0;
        cpu_data->dcache.sets           = 512;
        cpu_data->dcache.ways           = 1;
        cpu_data->dcache.linesz         = L1_CACHE_BYTES;
 
-       /* Set the FPU flag, virtually all SH-4's have one */
-       cpu_data->flags |= CPU_HAS_FPU;
+       /*
+        * Setup some generic flags we can probe
+        * (L2 and DSP detection only work on SH-4A)
+        */
+       if (((pvr >> 16) & 0xff) == 0x10) {
+               if ((cvr & 0x02000000) == 0)
+                       cpu_data->flags |= CPU_HAS_L2_CACHE;
+               if ((cvr & 0x10000000) == 0)
+                       cpu_data->flags |= CPU_HAS_DSP;
+
+               cpu_data->flags |= CPU_HAS_LLSC;
+       }
+
+       /* FPU detection works for everyone */
+       if ((cvr & 0x20000000) == 1)
+               cpu_data->flags |= CPU_HAS_FPU;
+
+       /* Mask off the upper chip ID */
+       pvr &= 0xffff;
 
        /*
         * Probe the underlying processor version/revision and
@@ -63,56 +78,101 @@ 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_PERF_COUNTER;
+               cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
+                                  CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA;
                break;
        case 0x206:
                cpu_data->type = CPU_SH7750S;
-               cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_PERF_COUNTER;
+               cpu_data->flags |= CPU_HAS_P2_FLUSH_BUG | CPU_HAS_FPU |
+                                  CPU_HAS_PERF_COUNTER | CPU_HAS_PTEA;
                break;
        case 0x1100:
                cpu_data->type = CPU_SH7751;
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
                break;
        case 0x2000:
                cpu_data->type = CPU_SH73180;
                cpu_data->icache.ways = 4;
                cpu_data->dcache.ways = 4;
-               cpu_data->flags &= ~CPU_HAS_FPU;
+               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;
+
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_LLSC;
+               break;
+       case 0x2006:
+       case 0x200A:
+               if (prr == 0x61)
+                       cpu_data->type = CPU_SH7781;
+               else
+                       cpu_data->type = CPU_SH7780;
+
+               cpu_data->icache.ways = 4;
+               cpu_data->dcache.ways = 4;
+
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PERF_COUNTER |
+                                  CPU_HAS_LLSC;
+               break;
+       case 0x3000:
+       case 0x3003:
+               cpu_data->type = CPU_SH7343;
+               cpu_data->icache.ways = 4;
+               cpu_data->dcache.ways = 4;
+               cpu_data->flags |= CPU_HAS_LLSC;
                break;
        case 0x8000:
                cpu_data->type = CPU_ST40RA;
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
                break;
        case 0x8100:
                cpu_data->type = CPU_ST40GX1;
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
                break;
        case 0x700:
                cpu_data->type = CPU_SH4_501;
                cpu_data->icache.ways = 2;
                cpu_data->dcache.ways = 2;
-
-               /* No FPU on the SH4-500 series.. */
-               cpu_data->flags &= ~CPU_HAS_FPU;
+               cpu_data->flags |= CPU_HAS_PTEA;
                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 | CPU_HAS_PTEA;
                break;
        case 0x500 ... 0x501:
                switch (prr) {
-                   case 0x10: cpu_data->type = CPU_SH7750R; break;
-                   case 0x11: cpu_data->type = CPU_SH7751R; break;
-                   case 0x50: cpu_data->type = CPU_SH7760;  break;
+               case 0x10:
+                       cpu_data->type = CPU_SH7750R;
+                       break;
+               case 0x11:
+                       cpu_data->type = CPU_SH7751R;
+                       break;
+               case 0x50 ... 0x5f:
+                       cpu_data->type = CPU_SH7760;
+                       break;
                }
 
                cpu_data->icache.ways = 2;
                cpu_data->dcache.ways = 2;
 
+               cpu_data->flags |= CPU_HAS_FPU | CPU_HAS_PTEA;
+
                break;
        default:
                cpu_data->type = CPU_SH_NONE;
                break;
        }
 
+#ifdef CONFIG_SH_DIRECT_MAPPED
+       cpu_data->icache.ways = 1;
+       cpu_data->dcache.ways = 1;
+#endif
+
        /*
         * On anything that's not a direct-mapped cache, look to the CVR
         * for I/D-cache specifics.
@@ -121,18 +181,56 @@ int __init detect_cpu_and_cache_system(void)
                size = sizes[(cvr >> 20) & 0xf];
                cpu_data->icache.way_incr       = (size >> 1);
                cpu_data->icache.sets           = (size >> 6);
-               cpu_data->icache.entry_mask     =
-                       (cpu_data->icache.way_incr - (1 << 5));
+
        }
 
+       /* Setup the rest of the I-cache info */
+       cpu_data->icache.entry_mask = cpu_data->icache.way_incr -
+                                     cpu_data->icache.linesz;
+
+       cpu_data->icache.way_size = cpu_data->icache.sets *
+                                   cpu_data->icache.linesz;
+
+       /* And the rest of the D-cache */
        if (cpu_data->dcache.ways > 1) {
                size = sizes[(cvr >> 16) & 0xf];
                cpu_data->dcache.way_incr       = (size >> 1);
                cpu_data->dcache.sets           = (size >> 6);
-               cpu_data->dcache.entry_mask     =
-                       (cpu_data->dcache.way_incr - (1 << 5));
+       }
+
+       cpu_data->dcache.entry_mask = cpu_data->dcache.way_incr -
+                                     cpu_data->dcache.linesz;
+
+       cpu_data->dcache.way_size = cpu_data->dcache.sets *
+                                   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) {
+               /*
+                * Size calculation is much more sensible
+                * than it is for the L1.
+                *
+                * Sizes are 128KB, 258KB, 512KB, and 1MB.
+                */
+               size = (cvr & 0xf) << 17;
+
+               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);
        }
 
        return 0;
 }
-
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c
new file mode 100644 (file)
index 0000000..6e4e965
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH4-202 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffe80000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 40, 41, 43, 42 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh4202_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh4202_devices_setup(void)
+{
+       return platform_add_devices(sh4202_devices,
+                                   ARRAY_SIZE(sh4202_devices));
+}
+__initcall(sh4202_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh73180.c b/arch/sh/kernel/cpu/sh4/setup-sh73180.c
new file mode 100644 (file)
index 0000000..cc9ea1e
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH73180 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffe80000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 80, 81, 83, 82 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh73180_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh73180_devices_setup(void)
+{
+       return platform_add_devices(sh73180_devices,
+                                   ARRAY_SIZE(sh73180_devices));
+}
+__initcall(sh73180_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7343.c b/arch/sh/kernel/cpu/sh4/setup-sh7343.c
new file mode 100644 (file)
index 0000000..91d61cf
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SH7343 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffe00000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 80, 81, 83, 82 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7343_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7343_devices_setup(void)
+{
+       return platform_add_devices(sh7343_devices,
+                                   ARRAY_SIZE(sh7343_devices));
+}
+__initcall(sh7343_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c
new file mode 100644 (file)
index 0000000..50812d5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SH7750/SH7751 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffe00000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCI,
+               .irqs           = { 23, 24, 25, 0 },
+       }, {
+               .mapbase        = 0xffe80000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 40, 41, 43, 42 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7750_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7750_devices_setup(void)
+{
+       return platform_add_devices(sh7750_devices,
+                                   ARRAY_SIZE(sh7750_devices));
+}
+__initcall(sh7750_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c
new file mode 100644 (file)
index 0000000..97f1c9a
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SH7760 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xfe600000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 52, 53, 55, 54 },
+       }, {
+               .mapbase        = 0xfe610000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 72, 73, 75, 74 },
+       }, {
+               .mapbase        = 0xfe620000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 76, 77, 79, 78 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7760_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7760_devices_setup(void)
+{
+       return platform_add_devices(sh7760_devices,
+                                   ARRAY_SIZE(sh7760_devices));
+}
+__initcall(sh7760_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7770.c b/arch/sh/kernel/cpu/sh4/setup-sh7770.c
new file mode 100644 (file)
index 0000000..6a04cc5
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SH7770 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xff923000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 61, 61, 61, 61 },
+       }, {
+               .mapbase        = 0xff924000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 62, 62, 62, 62 },
+       }, {
+               .mapbase        = 0xff925000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 63, 63, 63, 63 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7770_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7770_devices_setup(void)
+{
+       return platform_add_devices(sh7770_devices,
+                                   ARRAY_SIZE(sh7770_devices));
+}
+__initcall(sh7770_devices_setup);
diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7780.c b/arch/sh/kernel/cpu/sh4/setup-sh7780.c
new file mode 100644 (file)
index 0000000..72493f2
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * SH7780 Setup
+ *
+ *  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/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct resource rtc_resources[] = {
+       [0] = {
+               .start  = 0xffe80000,
+               .end    = 0xffe80000 + 0x58 - 1,
+               .flags  = IORESOURCE_IO,
+       },
+       [1] = {
+               /* Period IRQ */
+               .start  = 21,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [2] = {
+               /* Carry IRQ */
+               .start  = 22,
+               .flags  = IORESOURCE_IRQ,
+       },
+       [3] = {
+               /* Alarm IRQ */
+               .start  = 23,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device rtc_device = {
+       .name           = "sh-rtc",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(rtc_resources),
+       .resource       = rtc_resources,
+};
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffe00000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 40, 41, 43, 42 },
+       }, {
+               .mapbase        = 0xffe10000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 76, 77, 79, 78 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7780_devices[] __initdata = {
+       &rtc_device,
+       &sci_device,
+};
+
+static int __init sh7780_devices_setup(void)
+{
+       return platform_add_devices(sh7780_devices,
+                                   ARRAY_SIZE(sh7780_devices));
+}
+__initcall(sh7780_devices_setup);
index b09805f3ee23799e8a78379856211d2b967a30f0..7bcc73f9b8df535ad8887383aeac71a8b2491ef5 100644 (file)
@@ -1,49 +1,52 @@
 /*
- * arch/sh/kernel/cpu/sq.c
+ * arch/sh/kernel/cpu/sh4/sq.c
  *
  * General management API for SH-4 integrated Store Queues
  *
- * Copyright (C) 2001, 2002, 2003, 2004  Paul Mundt
+ * Copyright (C) 2001 - 2006  Paul Mundt
  * Copyright (C) 2001, 2002  M. R. Brown
  *
- * Some of this code has been adopted directly from the old arch/sh/mm/sq.c
- * hack that was part of the LinuxDC project. For all intents and purposes,
- * this is a completely new interface that really doesn't have much in common
- * with the old zone-based approach at all. In fact, it's only listed here for
- * general completeness.
- *
  * 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/cpu.h>
+#include <linux/bitmap.h>
+#include <linux/sysdev.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
 #include <linux/vmalloc.h>
-
+#include <linux/mm.h>
 #include <asm/io.h>
 #include <asm/page.h>
-#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
 #include <asm/cpu/sq.h>
 
-static LIST_HEAD(sq_mapping_list);
+struct sq_mapping;
+
+struct sq_mapping {
+       const char *name;
+
+       unsigned long sq_addr;
+       unsigned long addr;
+       unsigned int size;
+
+       struct sq_mapping *next;
+};
+
+static struct sq_mapping *sq_mapping_list;
 static DEFINE_SPINLOCK(sq_mapping_lock);
+static kmem_cache_t *sq_cache;
+static unsigned long *sq_bitmap;
 
-/**
- * sq_flush - Flush (prefetch) the store queue cache
- * @addr: the store queue address to flush
- *
- * Executes a prefetch instruction on the specified store queue cache,
- * so that the cached data is written to physical memory.
- */
-inline void sq_flush(void *addr)
-{
-       __asm__ __volatile__ ("pref @%0" : : "r" (addr) : "memory");
-}
+#define store_queue_barrier()                  \
+do {                                           \
+       (void)ctrl_inl(P4SEG_STORE_QUE);        \
+       ctrl_outl(0, P4SEG_STORE_QUE + 0);      \
+       ctrl_outl(0, P4SEG_STORE_QUE + 8);      \
+} while (0);
 
 /**
  * sq_flush_range - Flush (prefetch) a specific SQ range
@@ -56,152 +59,73 @@ inline void sq_flush(void *addr)
 void sq_flush_range(unsigned long start, unsigned int len)
 {
        volatile unsigned long *sq = (unsigned long *)start;
-       unsigned long dummy;
 
        /* Flush the queues */
        for (len >>= 5; len--; sq += 8)
-               sq_flush((void *)sq);
+               prefetchw((void *)sq);
 
        /* Wait for completion */
-       dummy = ctrl_inl(P4SEG_STORE_QUE);
-
-       ctrl_outl(0, P4SEG_STORE_QUE + 0);
-       ctrl_outl(0, P4SEG_STORE_QUE + 8);
+       store_queue_barrier();
 }
 
-static struct sq_mapping *__sq_alloc_mapping(unsigned long virt, unsigned long phys, unsigned long size, const char *name)
+static inline void sq_mapping_list_add(struct sq_mapping *map)
 {
-       struct sq_mapping *map;
-
-       if (virt + size > SQ_ADDRMAX)
-               return ERR_PTR(-ENOSPC);
-
-       map = kmalloc(sizeof(struct sq_mapping), GFP_KERNEL);
-       if (!map)
-               return ERR_PTR(-ENOMEM);
+       struct sq_mapping **p, *tmp;
 
-       INIT_LIST_HEAD(&map->list);
+       spin_lock_irq(&sq_mapping_lock);
 
-       map->sq_addr    = virt;
-       map->addr       = phys;
-       map->size       = size + 1;
-       map->name       = name;
+       p = &sq_mapping_list;
+       while ((tmp = *p) != NULL)
+               p = &tmp->next;
 
-       list_add(&map->list, &sq_mapping_list);
+       map->next = tmp;
+       *p = map;
 
-       return map;
+       spin_unlock_irq(&sq_mapping_lock);
 }
 
-static unsigned long __sq_get_next_addr(void)
+static inline void sq_mapping_list_del(struct sq_mapping *map)
 {
-       if (!list_empty(&sq_mapping_list)) {
-               struct list_head *pos, *tmp;
-
-               /*
-                * Read one off the list head, as it will have the highest
-                * mapped allocation. Set the next one up right above it.
-                *
-                * This is somewhat sub-optimal, as we don't look at
-                * gaps between allocations or anything lower then the
-                * highest-level allocation.
-                *
-                * However, in the interest of performance and the general
-                * lack of desire to do constant list rebalancing, we don't
-                * worry about it.
-                */
-               list_for_each_safe(pos, tmp, &sq_mapping_list) {
-                       struct sq_mapping *entry;
-
-                       entry = list_entry(pos, typeof(*entry), list);
-
-                       return entry->sq_addr + entry->size;
+       struct sq_mapping **p, *tmp;
+
+       spin_lock_irq(&sq_mapping_lock);
+
+       for (p = &sq_mapping_list; (tmp = *p); p = &tmp->next)
+               if (tmp == map) {
+                       *p = tmp->next;
+                       break;
                }
-       }
 
-       return P4SEG_STORE_QUE;
+       spin_unlock_irq(&sq_mapping_lock);
 }
 
-/**
- * __sq_remap - Perform a translation from the SQ to a phys addr
- * @map: sq mapping containing phys and store queue addresses.
- *
- * Maps the store queue address specified in the mapping to the physical
- * address specified in the mapping.
- */
-static struct sq_mapping *__sq_remap(struct sq_mapping *map)
+static int __sq_remap(struct sq_mapping *map, unsigned long flags)
 {
-       unsigned long flags, pteh, ptel;
+#if defined(CONFIG_MMU)
        struct vm_struct *vma;
-       pgprot_t pgprot;
-
-       /*
-        * Without an MMU (or with it turned off), this is much more
-        * straightforward, as we can just load up each queue's QACR with
-        * the physical address appropriately masked.
-        */
-
-       ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0);
-       ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1);
 
-#ifdef CONFIG_MMU
-       /*
-        * With an MMU on the other hand, things are slightly more involved.
-        * Namely, we have to have a direct mapping between the SQ addr and
-        * the associated physical address in the UTLB by way of setting up
-        * a virt<->phys translation by hand. We do this by simply specifying
-        * the SQ addr in UTLB.VPN and the associated physical address in
-        * UTLB.PPN.
-        *
-        * Notably, even though this is a special case translation, and some
-        * of the configuration bits are meaningless, we're still required
-        * to have a valid ASID context in PTEH.
-        *
-        * We could also probably get by without explicitly setting PTEA, but
-        * we do it here just for good measure.
-        */
-       spin_lock_irqsave(&sq_mapping_lock, flags);
-
-       pteh = map->sq_addr;
-       ctrl_outl((pteh & MMU_VPN_MASK) | get_asid(), MMU_PTEH);
-
-       ptel = map->addr & PAGE_MASK;
-       ctrl_outl(((ptel >> 28) & 0xe) | (ptel & 0x1), MMU_PTEA);
-
-       pgprot = pgprot_noncached(PAGE_KERNEL);
-
-       ptel &= _PAGE_FLAGS_HARDWARE_MASK;
-       ptel |= pgprot_val(pgprot);
-       ctrl_outl(ptel, MMU_PTEL);
-
-       __asm__ __volatile__ ("ldtlb" : : : "memory");
-
-       spin_unlock_irqrestore(&sq_mapping_lock, flags);
-
-       /*
-        * Next, we need to map ourselves in the kernel page table, so that
-        * future accesses after a TLB flush will be handled when we take a
-        * page fault.
-        *
-        * Theoretically we could just do this directly and not worry about
-        * setting up the translation by hand ahead of time, but for the
-        * cases where we want a one-shot SQ mapping followed by a quick
-        * writeout before we hit the TLB flush, we do it anyways. This way
-        * we at least save ourselves the initial page fault overhead.
-        */
        vma = __get_vm_area(map->size, VM_ALLOC, map->sq_addr, SQ_ADDRMAX);
        if (!vma)
-               return ERR_PTR(-ENOMEM);
+               return -ENOMEM;
 
        vma->phys_addr = map->addr;
 
        if (remap_area_pages((unsigned long)vma->addr, vma->phys_addr,
-                            map->size, pgprot_val(pgprot))) {
+                            map->size, flags)) {
                vunmap(vma->addr);
-               return NULL;
+               return -EAGAIN;
        }
-#endif /* CONFIG_MMU */
+#else
+       /*
+        * Without an MMU (or with it turned off), this is much more
+        * straightforward, as we can just load up each queue's QACR with
+        * the physical address appropriately masked.
+        */
+       ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0);
+       ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1);
+#endif
 
-       return map;
+       return 0;
 }
 
 /**
@@ -209,42 +133,65 @@ static struct sq_mapping *__sq_remap(struct sq_mapping *map)
  * @phys: Physical address of mapping.
  * @size: Length of mapping.
  * @name: User invoking mapping.
+ * @flags: Protection flags.
  *
  * Remaps the physical address @phys through the next available store queue
  * address of @size length. @name is logged at boot time as well as through
- * the procfs interface.
- *
- * A pre-allocated and filled sq_mapping pointer is returned, and must be
- * cleaned up with a call to sq_unmap() when the user is done with the
- * mapping.
+ * the sysfs interface.
  */
-struct sq_mapping *sq_remap(unsigned long phys, unsigned int size, const char *name)
+unsigned long sq_remap(unsigned long phys, unsigned int size,
+                      const char *name, unsigned long flags)
 {
        struct sq_mapping *map;
-       unsigned long virt, end;
+       unsigned long end;
        unsigned int psz;
+       int ret, page;
 
        /* Don't allow wraparound or zero size */
        end = phys + size - 1;
-       if (!size || end < phys)
-               return NULL;
+       if (unlikely(!size || end < phys))
+               return -EINVAL;
        /* Don't allow anyone to remap normal memory.. */
-       if (phys < virt_to_phys(high_memory))
-               return NULL;
+       if (unlikely(phys < virt_to_phys(high_memory)))
+               return -EINVAL;
 
        phys &= PAGE_MASK;
+       size = PAGE_ALIGN(end + 1) - phys;
+
+       map = kmem_cache_alloc(sq_cache, GFP_KERNEL);
+       if (unlikely(!map))
+               return -ENOMEM;
+
+       map->addr = phys;
+       map->size = size;
+       map->name = name;
+
+       page = bitmap_find_free_region(sq_bitmap, 0x04000000,
+                                      get_order(map->size));
+       if (unlikely(page < 0)) {
+               ret = -ENOSPC;
+               goto out;
+       }
+
+       map->sq_addr = P4SEG_STORE_QUE + (page << PAGE_SHIFT);
+
+       ret = __sq_remap(map, flags);
+       if (unlikely(ret != 0))
+               goto out;
+
+       psz = (size + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+       pr_info("sqremap: %15s  [%4d page%s]  va 0x%08lx   pa 0x%08lx\n",
+               likely(map->name) ? map->name : "???",
+               psz, psz == 1 ? " " : "s",
+               map->sq_addr, map->addr);
 
-       size  = PAGE_ALIGN(end + 1) - phys;
-       virt  = __sq_get_next_addr();
-       psz   = (size + (PAGE_SIZE - 1)) / PAGE_SIZE;
-       map   = __sq_alloc_mapping(virt, phys, size, name);
+       sq_mapping_list_add(map);
 
-       printk("sqremap: %15s  [%4d page%s]  va 0x%08lx   pa 0x%08lx\n",
-              map->name ? map->name : "???",
-              psz, psz == 1 ? " " : "s",
-              map->sq_addr, map->addr);
+       return map->sq_addr;
 
-       return __sq_remap(map);
+out:
+       kmem_cache_free(sq_cache, map);
+       return ret;
 }
 
 /**
@@ -255,188 +202,198 @@ struct sq_mapping *sq_remap(unsigned long phys, unsigned int size, const char *n
  * sq_remap(). Also frees up the pte that was previously inserted into
  * the kernel page table and discards the UTLB translation.
  */
-void sq_unmap(struct sq_mapping *map)
+void sq_unmap(unsigned long vaddr)
 {
-       if (map->sq_addr > (unsigned long)high_memory)
-               vfree((void *)(map->sq_addr & PAGE_MASK));
+       struct sq_mapping **p, *map;
+       struct vm_struct *vma;
+       int page;
 
-       list_del(&map->list);
-       kfree(map);
-}
+       for (p = &sq_mapping_list; (map = *p); p = &map->next)
+               if (map->sq_addr == vaddr)
+                       break;
 
-/**
- * sq_clear - Clear a store queue range
- * @addr: Address to start clearing from.
- * @len: Length to clear.
- *
- * A quick zero-fill implementation for clearing out memory that has been
- * remapped through the store queues.
- */
-void sq_clear(unsigned long addr, unsigned int len)
-{
-       int i;
+       if (unlikely(!map)) {
+               printk("%s: bad store queue address 0x%08lx\n",
+                      __FUNCTION__, vaddr);
+               return;
+       }
 
-       /* Clear out both queues linearly */
-       for (i = 0; i < 8; i++) {
-               ctrl_outl(0, addr + i + 0);
-               ctrl_outl(0, addr + i + 8);
+       page = (map->sq_addr - P4SEG_STORE_QUE) >> PAGE_SHIFT;
+       bitmap_release_region(sq_bitmap, page, get_order(map->size));
+
+#ifdef CONFIG_MMU
+       vma = remove_vm_area((void *)(map->sq_addr & PAGE_MASK));
+       if (!vma) {
+               printk(KERN_ERR "%s: bad address 0x%08lx\n",
+                      __FUNCTION__, map->sq_addr);
+               return;
        }
+#endif
+
+       sq_mapping_list_del(map);
 
-       sq_flush_range(addr, len);
+       kmem_cache_free(sq_cache, map);
 }
 
-/**
- * sq_vma_unmap - Unmap a VMA range
- * @area: VMA containing range.
- * @addr: Start of range.
- * @len: Length of range.
+/*
+ * Needlessly complex sysfs interface. Unfortunately it doesn't seem like
+ * there is any other easy way to add things on a per-cpu basis without
+ * putting the directory entries somewhere stupid and having to create
+ * links in sysfs by hand back in to the per-cpu directories.
  *
- * Searches the sq_mapping_list for a mapping matching the sq addr @addr,
- * and subsequently frees up the entry. Further cleanup is done by generic
- * code.
+ * Some day we may want to have an additional abstraction per store
+ * queue, but considering the kobject hell we already have to deal with,
+ * it's simply not worth the trouble.
  */
-static void sq_vma_unmap(struct vm_area_struct *area,
-                        unsigned long addr, size_t len)
-{
-       struct list_head *pos, *tmp;
+static struct kobject *sq_kobject[NR_CPUS];
 
-       list_for_each_safe(pos, tmp, &sq_mapping_list) {
-               struct sq_mapping *entry;
+struct sq_sysfs_attr {
+       struct attribute attr;
+       ssize_t (*show)(char *buf);
+       ssize_t (*store)(const char *buf, size_t count);
+};
 
-               entry = list_entry(pos, typeof(*entry), list);
+#define to_sq_sysfs_attr(attr) container_of(attr, struct sq_sysfs_attr, attr)
 
-               if (entry->sq_addr == addr) {
-                       /*
-                        * We could probably get away without doing the tlb flush
-                        * here, as generic code should take care of most of this
-                        * when unmapping the rest of the VMA range for us. Leave
-                        * it in for added sanity for the time being..
-                        */
-                       __flush_tlb_page(get_asid(), entry->sq_addr & PAGE_MASK);
+static ssize_t sq_sysfs_show(struct kobject *kobj, struct attribute *attr,
+                            char *buf)
+{
+       struct sq_sysfs_attr *sattr = to_sq_sysfs_attr(attr);
 
-                       list_del(&entry->list);
-                       kfree(entry);
+       if (likely(sattr->show))
+               return sattr->show(buf);
 
-                       return;
-               }
-       }
+       return -EIO;
 }
 
-/**
- * sq_vma_sync - Sync a VMA range
- * @area: VMA containing range.
- * @start: Start of range.
- * @len: Length of range.
- * @flags: Additional flags.
- *
- * Synchronizes an sq mapped range by flushing the store queue cache for
- * the duration of the mapping.
- *
- * Used internally for user mappings, which must use msync() to prefetch
- * the store queue cache.
- */
-static int sq_vma_sync(struct vm_area_struct *area,
-                      unsigned long start, size_t len, unsigned int flags)
+static ssize_t sq_sysfs_store(struct kobject *kobj, struct attribute *attr,
+                             const char *buf, size_t count)
 {
-       sq_flush_range(start, len);
+       struct sq_sysfs_attr *sattr = to_sq_sysfs_attr(attr);
 
-       return 0;
+       if (likely(sattr->store))
+               return sattr->store(buf, count);
+
+       return -EIO;
 }
 
-static struct vm_operations_struct sq_vma_ops = {
-       .unmap  = sq_vma_unmap,
-       .sync   = sq_vma_sync,
-};
+static ssize_t mapping_show(char *buf)
+{
+       struct sq_mapping **list, *entry;
+       char *p = buf;
 
-/**
- * sq_mmap - mmap() for /dev/cpu/sq
- * @file: unused.
- * @vma: VMA to remap.
- *
- * Remap the specified vma @vma through the store queues, and setup associated
- * information for the new mapping. Also build up the page tables for the new
- * area.
- */
-static int sq_mmap(struct file *file, struct vm_area_struct *vma)
+       for (list = &sq_mapping_list; (entry = *list); list = &entry->next)
+               p += sprintf(p, "%08lx-%08lx [%08lx]: %s\n",
+                            entry->sq_addr, entry->sq_addr + entry->size,
+                            entry->addr, entry->name);
+
+       return p - buf;
+}
+
+static ssize_t mapping_store(const char *buf, size_t count)
 {
-       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-       unsigned long size = vma->vm_end - vma->vm_start;
-       struct sq_mapping *map;
+       unsigned long base = 0, len = 0;
 
-       /*
-        * We're not interested in any arbitrary virtual address that has
-        * been stuck in the VMA, as we already know what addresses we
-        * want. Save off the size, and reposition the VMA to begin at
-        * the next available sq address.
-        */
-       vma->vm_start = __sq_get_next_addr();
-       vma->vm_end   = vma->vm_start + size;
+       sscanf(buf, "%lx %lx", &base, &len);
+       if (!base)
+               return -EIO;
 
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       if (likely(len)) {
+               int ret = sq_remap(base, len, "Userspace",
+                                  pgprot_val(PAGE_SHARED));
+               if (ret < 0)
+                       return ret;
+       } else
+               sq_unmap(base);
 
-       vma->vm_flags |= VM_IO | VM_RESERVED;
+       return count;
+}
 
-       map = __sq_alloc_mapping(vma->vm_start, offset, size, "Userspace");
+static struct sq_sysfs_attr mapping_attr =
+       __ATTR(mapping, 0644, mapping_show, mapping_store);
 
-       if (io_remap_pfn_range(vma, map->sq_addr, map->addr >> PAGE_SHIFT,
-                               size, vma->vm_page_prot))
-               return -EAGAIN;
+static struct attribute *sq_sysfs_attrs[] = {
+       &mapping_attr.attr,
+       NULL,
+};
 
-       vma->vm_ops = &sq_vma_ops;
+static struct sysfs_ops sq_sysfs_ops = {
+       .show   = sq_sysfs_show,
+       .store  = sq_sysfs_store,
+};
 
-       return 0;
-}
+static struct kobj_type ktype_percpu_entry = {
+       .sysfs_ops      = &sq_sysfs_ops,
+       .default_attrs  = sq_sysfs_attrs,
+};
 
-#ifdef CONFIG_PROC_FS
-static int sq_mapping_read_proc(char *buf, char **start, off_t off,
-                               int len, int *eof, void *data)
+static int __devinit sq_sysdev_add(struct sys_device *sysdev)
 {
-       struct list_head *pos;
-       char *p = buf;
+       unsigned int cpu = sysdev->id;
+       struct kobject *kobj;
 
-       list_for_each_prev(pos, &sq_mapping_list) {
-               struct sq_mapping *entry;
+       sq_kobject[cpu] = kzalloc(sizeof(struct kobject), GFP_KERNEL);
+       if (unlikely(!sq_kobject[cpu]))
+               return -ENOMEM;
 
-               entry = list_entry(pos, typeof(*entry), list);
+       kobj = sq_kobject[cpu];
+       kobj->parent = &sysdev->kobj;
+       kobject_set_name(kobj, "%s", "sq");
+       kobj->ktype = &ktype_percpu_entry;
 
-               p += sprintf(p, "%08lx-%08lx [%08lx]: %s\n", entry->sq_addr,
-                            entry->sq_addr + entry->size - 1, entry->addr,
-                            entry->name);
-       }
-
-       return p - buf;
+       return kobject_register(kobj);
 }
-#endif
 
-static struct file_operations sq_fops = {
-       .owner          = THIS_MODULE,
-       .mmap           = sq_mmap,
-};
+static int __devexit sq_sysdev_remove(struct sys_device *sysdev)
+{
+       unsigned int cpu = sysdev->id;
+       struct kobject *kobj = sq_kobject[cpu];
 
-static struct miscdevice sq_dev = {
-       .minor          = STORE_QUEUE_MINOR,
-       .name           = "sq",
-       .fops           = &sq_fops,
+       kobject_unregister(kobj);
+       return 0;
+}
+
+static struct sysdev_driver sq_sysdev_driver = {
+       .add            = sq_sysdev_add,
+       .remove         = __devexit_p(sq_sysdev_remove),
 };
 
 static int __init sq_api_init(void)
 {
-       int ret;
+       unsigned int nr_pages = 0x04000000 >> PAGE_SHIFT;
+       unsigned int size = (nr_pages + (BITS_PER_LONG - 1)) / BITS_PER_LONG;
+       int ret = -ENOMEM;
+
        printk(KERN_NOTICE "sq: Registering store queue API.\n");
 
-       create_proc_read_entry("sq_mapping", 0, 0, sq_mapping_read_proc, 0);
+       sq_cache = kmem_cache_create("store_queue_cache",
+                               sizeof(struct sq_mapping), 0, 0,
+                               NULL, NULL);
+       if (unlikely(!sq_cache))
+               return ret;
 
-       ret = misc_register(&sq_dev);
-       if (ret)
-               remove_proc_entry("sq_mapping", NULL);
+       sq_bitmap = kzalloc(size, GFP_KERNEL);
+       if (unlikely(!sq_bitmap))
+               goto out;
+
+       ret = sysdev_driver_register(&cpu_sysdev_class, &sq_sysdev_driver);
+       if (unlikely(ret != 0))
+               goto out;
+
+       return 0;
+
+out:
+       kfree(sq_bitmap);
+       kmem_cache_destroy(sq_cache);
 
        return ret;
 }
 
 static void __exit sq_api_exit(void)
 {
-       misc_deregister(&sq_dev);
-       remove_proc_entry("sq_mapping", NULL);
+       sysdev_driver_unregister(&cpu_sysdev_class, &sq_sysdev_driver);
+       kfree(sq_bitmap);
+       kmem_cache_destroy(sq_cache);
 }
 
 module_init(sq_api_init);
@@ -445,11 +402,7 @@ module_exit(sq_api_exit);
 MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
 MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(STORE_QUEUE_MINOR);
 
 EXPORT_SYMBOL(sq_remap);
 EXPORT_SYMBOL(sq_unmap);
-EXPORT_SYMBOL(sq_clear);
-EXPORT_SYMBOL(sq_flush);
 EXPORT_SYMBOL(sq_flush_range);
-
index 1378db375e175c9905f583382ab02bacbec9d54d..a00022722e9e43c8ee4734e539ac97383be6790d 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1999, 2000  Niibe Yutaka
  *  Copyright (C) 2002  M. R. Brown
- *  Copyright (C) 2004  Paul Mundt
+ *  Copyright (C) 2004 - 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
@@ -49,7 +49,7 @@ static int __init sh_console_setup(struct console *co, char *options)
        return 0;
 }
 
-static struct console early_console = {
+static struct console bios_console = {
        .name           = "bios",
        .write          = sh_console_write,
        .setup          = sh_console_setup,
@@ -59,34 +59,43 @@ static struct console early_console = {
 #endif
 
 #ifdef CONFIG_EARLY_SCIF_CONSOLE
+#include <linux/serial_core.h>
+#include "../../../drivers/serial/sh-sci.h"
+
+#ifdef CONFIG_CPU_SH4
 #define SCIF_REG       0xffe80000
+#elif defined(CONFIG_CPU_SUBTYPE_SH72060)
+#define SCIF_REG       0xfffe9800
+#else
+#error "Undefined SCIF for this subtype"
+#endif
+
+static struct uart_port scif_port = {
+       .mapbase        = SCIF_REG,
+       .membase        = (char __iomem *)SCIF_REG,
+};
 
 static void scif_sercon_putc(int c)
 {
-       while (!(ctrl_inw(SCIF_REG + 0x10) & 0x20)) ;
+       while (((sci_in(&scif_port, SCFDR) & 0x1f00 >> 8) == 16))
+               ;
 
-       ctrl_outb(c, SCIF_REG + 12);
-       ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0x9f), SCIF_REG + 0x10);
+       sci_out(&scif_port, SCxTDR, c);
+       sci_in(&scif_port, SCxSR);
+       sci_out(&scif_port, SCxSR, 0xf3 & ~(0x20 | 0x40));
+
+       while ((sci_in(&scif_port, SCxSR) & 0x40) == 0);
+               ;
 
        if (c == '\n')
                scif_sercon_putc('\r');
 }
 
-static void scif_sercon_flush(void)
-{
-       ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
-
-       while (!(ctrl_inw(SCIF_REG + 0x10) & 0x40)) ;
-
-       ctrl_outw((ctrl_inw(SCIF_REG + 0x10) & 0xbf), SCIF_REG + 0x10);
-}
-
-static void scif_sercon_write(struct console *con, const char *s, unsigned count)
+static void scif_sercon_write(struct console *con, const char *s,
+                             unsigned count)
 {
        while (count-- > 0)
                scif_sercon_putc(*s++);
-
-       scif_sercon_flush();
 }
 
 static int __init scif_sercon_setup(struct console *con, char *options)
@@ -96,7 +105,7 @@ static int __init scif_sercon_setup(struct console *con, char *options)
        return 0;
 }
 
-static struct console early_console = {
+static struct console scif_console = {
        .name           = "sercon",
        .write          = scif_sercon_write,
        .setup          = scif_sercon_setup,
@@ -104,7 +113,7 @@ static struct console early_console = {
        .index          = -1,
 };
 
-void scif_sercon_init(int baud)
+static void scif_sercon_init(int baud)
 {
        ctrl_outw(0, SCIF_REG + 8);
        ctrl_outw(0, SCIF_REG);
@@ -122,16 +131,61 @@ void scif_sercon_init(int baud)
 }
 #endif
 
-void __init enable_early_printk(void)
+/*
+ * Setup a default console, if more than one is compiled in, rely on the
+ * earlyprintk= parsing to give priority.
+ */
+static struct console *early_console =
+#ifdef CONFIG_SH_STANDARD_BIOS
+       &bios_console
+#elif defined(CONFIG_EARLY_SCIF_CONSOLE)
+       &scif_console
+#else
+       NULL
+#endif
+       ;
+
+static int __initdata keep_early;
+
+int __init setup_early_printk(char *opt)
 {
-#ifdef CONFIG_EARLY_SCIF_CONSOLE
-       scif_sercon_init(115200);
+       char *space;
+       char buf[256];
+
+       strlcpy(buf, opt, sizeof(buf));
+       space = strchr(buf, ' ');
+       if (space)
+               *space = 0;
+
+       if (strstr(buf, "keep"))
+               keep_early = 1;
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+       if (!strncmp(buf, "bios", 4))
+               early_console = &bios_console;
+#endif
+#if defined(CONFIG_EARLY_SCIF_CONSOLE)
+       if (!strncmp(buf, "serial", 6)) {
+               early_console = &scif_console;
+
+#ifdef CONFIG_CPU_SH4
+               scif_sercon_init(115200);
+#endif
+       }
 #endif
-       register_console(&early_console);
+
+       if (likely(early_console))
+               register_console(early_console);
+
+       return 1;
 }
+__setup("earlyprintk=", setup_early_printk);
 
-void disable_early_printk(void)
+void __init disable_early_printk(void)
 {
-       unregister_console(&early_console);
+       if (!keep_early) {
+               printk("disabling early console\n");
+               unregister_console(early_console);
+       } else
+               printk("keeping early console\n");
 }
-
index 7dfd2ba75f7fb9d96fa1dcdfff8c2ce9475ff7ae..fe8221855b282648f25472cd64286814728f7843 100644 (file)
 #include <asm/cpu/mmu_context.h>
 #include <asm/unistd.h>
 
-#if !defined(CONFIG_NFSD) && !defined(CONFIG_NFSD_MODULE)
-#define sys_nfsservctl         sys_ni_syscall
-#endif
-
-#if !defined(CONFIG_MMU)
-#define sys_madvise            sys_ni_syscall
-#define sys_readahead          sys_ni_syscall
-#define sys_mprotect           sys_ni_syscall
-#define sys_msync              sys_ni_syscall
-#define sys_mlock              sys_ni_syscall
-#define sys_munlock            sys_ni_syscall
-#define sys_mlockall           sys_ni_syscall
-#define sys_munlockall         sys_ni_syscall
-#define sys_mremap             sys_ni_syscall
-#define sys_mincore            sys_ni_syscall
-#define sys_remap_file_pages   sys_ni_syscall
-#endif
-
 ! NOTE:
 ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address
 ! to be jumped is too far, but it causes illegal slot exception.
@@ -326,7 +308,7 @@ ENTRY(exception_error)
        .align  2
 ret_from_exception:
        preempt_stop()
-ret_from_irq:
+ENTRY(ret_from_irq)
        !
        mov     #OFF_SR, r0
        mov.l   @(r0,r15), r0   ! get status register
@@ -389,11 +371,12 @@ work_pending:
        ! r8: current_thread_info
        ! t:  result of "tst    #_TIF_NEED_RESCHED, r0"
        bf/s    work_resched
-        tst    #_TIF_SIGPENDING, r0
+        tst    #(_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r0
 work_notifysig:
        bt/s    restore_all
         mov    r15, r4
-       mov     #0, r5
+       mov     r12, r5         ! set arg1(save_r0)
+       mov     r0, r6
        mov.l   2f, r1
        mova    restore_all, r0
        jmp     @r1
@@ -431,7 +414,7 @@ work_resched:
 
        .align  2
 1:     .long   schedule
-2:     .long   do_signal
+2:     .long   do_notify_resume
 
        .align  2
 syscall_exit_work:
@@ -552,6 +535,7 @@ syscall_call:
        mov.l   @r9, r8
        jsr     @r8             ! jump to specific syscall handler
         nop
+       mov.l   @(OFF_R0,r15), r12              ! save r0
        mov.l   r0, @(OFF_R0,r15)               ! save the return value
        !
 syscall_exit:
@@ -644,7 +628,7 @@ skip_restore:
        !
 #if defined(CONFIG_KGDB_NMI)
        ! Clear in_nmi
-       mov.l   4f, k0
+       mov.l   6f, k0
        mov     #0, k1
        mov.b   k1, @k0
 #endif
@@ -722,7 +706,7 @@ interrupt:
 !
 !
        .align  2
-handle_exception:
+ENTRY(handle_exception)
        ! Using k0, k1 for scratch registers (r0_bank1, r1_bank),
        ! save all registers onto stack.
        !
@@ -732,8 +716,8 @@ handle_exception:
        bt/s    1f              ! It's a kernel to kernel transition.
         mov    r15, k0         ! save original stack to k0
        /* User space to kernel */
-       mov     #0x20, k1
-       shll8   k1              ! k1 := 8192 (== THREAD_SIZE)
+       mov     #(THREAD_SIZE >> 8), k1
+       shll8   k1              ! k1 := THREAD_SIZE
        add     current, k1
        mov     k1, r15         ! change to kernel stack
        !
@@ -838,300 +822,3 @@ ENTRY(exception_none)
        rts
         nop
 
-       .data
-ENTRY(sys_call_table)
-       .long sys_ni_syscall    /* 0  -  old "setup()" system call*/
-       .long sys_exit
-       .long sys_fork
-       .long sys_read
-       .long sys_write
-       .long sys_open          /* 5 */
-       .long sys_close
-       .long sys_waitpid
-       .long sys_creat
-       .long sys_link
-       .long sys_unlink                /* 10 */
-       .long sys_execve
-       .long sys_chdir
-       .long sys_time
-       .long sys_mknod
-       .long sys_chmod         /* 15 */
-       .long sys_lchown16
-       .long sys_ni_syscall    /* old break syscall holder */
-       .long sys_stat
-       .long sys_lseek
-       .long sys_getpid                /* 20 */
-       .long sys_mount
-       .long sys_oldumount
-       .long sys_setuid16
-       .long sys_getuid16
-       .long sys_stime         /* 25 */
-       .long sys_ptrace
-       .long sys_alarm
-       .long sys_fstat
-       .long sys_pause
-       .long sys_utime         /* 30 */
-       .long sys_ni_syscall    /* old stty syscall holder */
-       .long sys_ni_syscall    /* old gtty syscall holder */
-       .long sys_access
-       .long sys_nice
-       .long sys_ni_syscall    /* 35 */                /* old ftime syscall holder */
-       .long sys_sync
-       .long sys_kill
-       .long sys_rename
-       .long sys_mkdir
-       .long sys_rmdir         /* 40 */
-       .long sys_dup
-       .long sys_pipe
-       .long sys_times
-       .long sys_ni_syscall    /* old prof syscall holder */
-       .long sys_brk           /* 45 */
-       .long sys_setgid16
-       .long sys_getgid16
-       .long sys_signal
-       .long sys_geteuid16
-       .long sys_getegid16     /* 50 */
-       .long sys_acct
-       .long sys_umount                /* recycled never used phys() */
-       .long sys_ni_syscall    /* old lock syscall holder */
-       .long sys_ioctl
-       .long sys_fcntl         /* 55 */
-       .long sys_ni_syscall    /* old mpx syscall holder */
-       .long sys_setpgid
-       .long sys_ni_syscall    /* old ulimit syscall holder */
-       .long sys_ni_syscall    /* sys_olduname */
-       .long sys_umask         /* 60 */
-       .long sys_chroot
-       .long sys_ustat
-       .long sys_dup2
-       .long sys_getppid
-       .long sys_getpgrp               /* 65 */
-       .long sys_setsid
-       .long sys_sigaction
-       .long sys_sgetmask
-       .long sys_ssetmask
-       .long sys_setreuid16    /* 70 */
-       .long sys_setregid16
-       .long sys_sigsuspend
-       .long sys_sigpending
-       .long sys_sethostname
-       .long sys_setrlimit     /* 75 */
-       .long sys_old_getrlimit
-       .long sys_getrusage
-       .long sys_gettimeofday
-       .long sys_settimeofday
-       .long sys_getgroups16   /* 80 */
-       .long sys_setgroups16
-       .long sys_ni_syscall    /* sys_oldselect */
-       .long sys_symlink
-       .long sys_lstat
-       .long sys_readlink              /* 85 */
-       .long sys_uselib
-       .long sys_swapon
-       .long sys_reboot
-       .long old_readdir
-       .long old_mmap          /* 90 */
-       .long sys_munmap
-       .long sys_truncate
-       .long sys_ftruncate
-       .long sys_fchmod
-       .long sys_fchown16              /* 95 */
-       .long sys_getpriority
-       .long sys_setpriority
-       .long sys_ni_syscall    /* old profil syscall holder */
-       .long sys_statfs
-       .long sys_fstatfs               /* 100 */
-       .long sys_ni_syscall    /* ioperm */
-       .long sys_socketcall
-       .long sys_syslog
-       .long sys_setitimer
-       .long sys_getitimer     /* 105 */
-       .long sys_newstat
-       .long sys_newlstat
-       .long sys_newfstat
-       .long sys_uname
-       .long sys_ni_syscall    /* 110 */ /* iopl */
-       .long sys_vhangup
-       .long sys_ni_syscall    /* idle */
-       .long sys_ni_syscall    /* vm86old */
-       .long sys_wait4
-       .long sys_swapoff               /* 115 */
-       .long sys_sysinfo
-       .long sys_ipc
-       .long sys_fsync
-       .long sys_sigreturn
-       .long sys_clone         /* 120 */
-       .long sys_setdomainname
-       .long sys_newuname
-       .long sys_ni_syscall    /* sys_modify_ldt */
-       .long sys_adjtimex
-       .long sys_mprotect              /* 125 */
-       .long sys_sigprocmask
-       .long sys_ni_syscall    /* old "create_module" */
-       .long sys_init_module
-       .long sys_delete_module
-       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
-       .long sys_quotactl
-       .long sys_getpgid
-       .long sys_fchdir
-       .long sys_bdflush
-       .long sys_sysfs         /* 135 */
-       .long sys_personality
-       .long sys_ni_syscall    /* for afs_syscall */
-       .long sys_setfsuid16
-       .long sys_setfsgid16
-       .long sys_llseek                /* 140 */
-       .long sys_getdents
-       .long sys_select
-       .long sys_flock
-       .long sys_msync
-       .long sys_readv         /* 145 */
-       .long sys_writev
-       .long sys_getsid
-       .long sys_fdatasync
-       .long sys_sysctl
-       .long sys_mlock         /* 150 */
-       .long sys_munlock
-       .long sys_mlockall
-       .long sys_munlockall
-       .long sys_sched_setparam
-       .long sys_sched_getparam   /* 155 */
-       .long sys_sched_setscheduler
-       .long sys_sched_getscheduler
-       .long sys_sched_yield
-       .long sys_sched_get_priority_max
-       .long sys_sched_get_priority_min  /* 160 */
-       .long sys_sched_rr_get_interval
-       .long sys_nanosleep
-       .long sys_mremap
-       .long sys_setresuid16
-       .long sys_getresuid16   /* 165 */
-       .long sys_ni_syscall    /* vm86 */
-       .long sys_ni_syscall    /* old "query_module" */
-       .long sys_poll
-       .long sys_nfsservctl
-       .long sys_setresgid16   /* 170 */
-       .long sys_getresgid16
-       .long sys_prctl
-       .long sys_rt_sigreturn
-       .long sys_rt_sigaction
-       .long sys_rt_sigprocmask        /* 175 */
-       .long sys_rt_sigpending
-       .long sys_rt_sigtimedwait
-       .long sys_rt_sigqueueinfo
-       .long sys_rt_sigsuspend
-       .long sys_pread_wrapper    /* 180 */
-       .long sys_pwrite_wrapper
-       .long sys_chown16
-       .long sys_getcwd
-       .long sys_capget
-       .long sys_capset           /* 185 */
-       .long sys_sigaltstack
-       .long sys_sendfile
-       .long sys_ni_syscall    /* streams1 */
-       .long sys_ni_syscall    /* streams2 */
-       .long sys_vfork            /* 190 */
-       .long sys_getrlimit
-       .long sys_mmap2
-       .long sys_truncate64
-       .long sys_ftruncate64
-       .long sys_stat64                /* 195 */
-       .long sys_lstat64
-       .long sys_fstat64
-       .long sys_lchown
-       .long sys_getuid
-       .long sys_getgid                /* 200 */
-       .long sys_geteuid
-       .long sys_getegid
-       .long sys_setreuid
-       .long sys_setregid
-       .long sys_getgroups     /* 205 */
-       .long sys_setgroups
-       .long sys_fchown
-       .long sys_setresuid
-       .long sys_getresuid
-       .long sys_setresgid     /* 210 */
-       .long sys_getresgid
-       .long sys_chown
-       .long sys_setuid
-       .long sys_setgid
-       .long sys_setfsuid              /* 215 */
-       .long sys_setfsgid
-       .long sys_pivot_root
-       .long sys_mincore
-       .long sys_madvise
-       .long sys_getdents64    /* 220 */
-       .long sys_fcntl64
-       .long sys_ni_syscall    /* reserved for TUX */
-       .long sys_ni_syscall    /* Reserved for Security */
-       .long sys_gettid
-       .long sys_readahead     /* 225 */
-       .long sys_setxattr
-       .long sys_lsetxattr
-       .long sys_fsetxattr
-       .long sys_getxattr
-       .long sys_lgetxattr     /* 230 */
-       .long sys_fgetxattr
-       .long sys_listxattr
-       .long sys_llistxattr
-       .long sys_flistxattr
-       .long sys_removexattr   /* 235 */
-       .long sys_lremovexattr
-       .long sys_fremovexattr
-       .long sys_tkill
-       .long sys_sendfile64
-       .long sys_futex         /* 240 */
-       .long sys_sched_setaffinity
-       .long sys_sched_getaffinity
-       .long sys_ni_syscall
-       .long sys_ni_syscall
-       .long sys_io_setup      /* 245 */
-       .long sys_io_destroy
-       .long sys_io_getevents
-       .long sys_io_submit
-       .long sys_io_cancel
-       .long sys_fadvise64     /* 250 */
-       .long sys_ni_syscall
-       .long sys_exit_group
-       .long sys_lookup_dcookie
-       .long sys_epoll_create
-       .long sys_epoll_ctl     /* 255 */
-       .long sys_epoll_wait
-       .long sys_remap_file_pages
-       .long sys_set_tid_address
-       .long sys_timer_create
-       .long sys_timer_settime         /* 260 */
-       .long sys_timer_gettime
-       .long sys_timer_getoverrun
-       .long sys_timer_delete
-       .long sys_clock_settime
-       .long sys_clock_gettime         /* 265 */
-       .long sys_clock_getres
-       .long sys_clock_nanosleep
-       .long sys_statfs64
-       .long sys_fstatfs64     
-       .long sys_tgkill                /* 270 */
-       .long sys_utimes
-       .long sys_fadvise64_64_wrapper
-       .long sys_ni_syscall    /* Reserved for vserver */
-       .long sys_ni_syscall    /* Reserved for mbind */
-       .long sys_ni_syscall    /* 275 - get_mempolicy */
-       .long sys_ni_syscall    /* set_mempolicy */
-       .long sys_mq_open
-       .long sys_mq_unlink
-       .long sys_mq_timedsend
-       .long sys_mq_timedreceive       /* 280 */
-       .long sys_mq_notify
-       .long sys_mq_getsetattr
-       .long sys_ni_syscall    /* Reserved for kexec */
-       .long sys_waitid
-       .long sys_add_key               /* 285 */
-       .long sys_request_key
-       .long sys_keyctl
-       .long sys_ioprio_set
-       .long sys_ioprio_get
-       .long sys_inotify_init          /* 290 */
-       .long sys_inotify_add_watch
-       .long sys_inotify_rm_watch
-
-/* End of entry.S */
index 9b9e6ef626cea4497f472c176b11355248ed55d5..f5f53d14f2456aaf61a9a0d34468efde924864b8 100644 (file)
  * Head.S contains the SH exception handlers and startup code.
  */
 #include <linux/linkage.h>
+#include <asm/thread_info.h>
+
+#ifdef CONFIG_CPU_SH4A
+#define SYNCO()                synco
+
+#define PREFI(label, reg)      \
+       mov.l   label, reg;     \
+       prefi   @reg
+#else
+#define SYNCO()
+#define PREFI(label, reg)
+#endif
 
        .section        .empty_zero_page, "aw"
 ENTRY(empty_zero_page)
@@ -42,18 +54,25 @@ ENTRY(_stext)
        !                       Initialize global interrupt mask
        mov     #0, r0
        ldc     r0, r6_bank
+
+       /*
+        * Prefetch if possible to reduce cache miss penalty.
+        *
+        * We do this early on for SH-4A as a micro-optimization,
+        * as later on we will have speculative execution enabled
+        * and this will become less of an issue.
+        */
+       PREFI(5f, r0)
+       PREFI(6f, r0)
+
        !
        mov.l   2f, r0
        mov     r0, r15         ! Set initial r15 (stack pointer)
-       mov     #0x20, r1       !
-       shll8   r1              ! r1 = 8192
+       mov     #(THREAD_SIZE >> 8), r1
+       shll8   r1              ! r1 = THREAD_SIZE
        sub     r1, r0          !
        ldc     r0, r7_bank     ! ... and initial thread_info
-       !
-       !                       Additional CPU initialization
-       mov.l   6f, r0
-       jsr     @r0
-        nop
+
        !                       Clear BSS area
        mov.l   3f, r1
        add     #4, r1
@@ -62,6 +81,14 @@ ENTRY(_stext)
 9:     cmp/hs  r2, r1
        bf/s    9b              ! while (r1 < r2)
         mov.l  r0,@-r2
+
+       !                       Additional CPU initialization
+       mov.l   6f, r0
+       jsr     @r0
+        nop
+
+       SYNCO()                 ! Wait for pending instructions..
+
        !                       Start kernel
        mov.l   5f, r0
        jmp     @r0
@@ -69,7 +96,7 @@ ENTRY(_stext)
 
        .balign 4
 1:     .long   0x400080F0              ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
-2:     .long   stack
+2:     .long   init_thread_union+THREAD_SIZE
 3:     .long   __bss_start
 4:     .long   _end
 5:     .long   start_kernel
index 71c9fde2fd9072517af4062168d720c2c3153b57..501fe03e3715770c484684f7b1fbecfb954d2010 100644 (file)
@@ -61,6 +61,73 @@ void memset_io(volatile void __iomem *dst, int c, unsigned long count)
 }
 EXPORT_SYMBOL(memset_io);
 
+void __raw_readsl(unsigned long addr, void *datap, int len)
+{
+       u32 *data;
+
+       for (data = datap; (len != 0) && (((u32)data & 0x1f) != 0); len--)
+               *data++ = ctrl_inl(addr);
+
+       if (likely(len >= (0x20 >> 2))) {
+               int tmp2, tmp3, tmp4, tmp5, tmp6;
+
+               __asm__ __volatile__(
+                       "1:                     \n\t"
+                       "mov.l  @%7, r0         \n\t"
+                       "mov.l  @%7, %2         \n\t"
+#ifdef CONFIG_CPU_SH4
+                       "movca.l r0, @%0        \n\t"
+#else
+                       "mov.l  r0, @%0         \n\t"
+#endif
+                       "mov.l  @%7, %3         \n\t"
+                       "mov.l  @%7, %4         \n\t"
+                       "mov.l  @%7, %5         \n\t"
+                       "mov.l  @%7, %6         \n\t"
+                       "mov.l  @%7, r7         \n\t"
+                       "mov.l  @%7, r0         \n\t"
+                       "mov.l  %2, @(0x04,%0)  \n\t"
+                       "mov    #0x20>>2, %2    \n\t"
+                       "mov.l  %3, @(0x08,%0)  \n\t"
+                       "sub    %2, %1          \n\t"
+                       "mov.l  %4, @(0x0c,%0)  \n\t"
+                       "cmp/hi %1, %2          ! T if 32 > len \n\t"
+                       "mov.l  %5, @(0x10,%0)  \n\t"
+                       "mov.l  %6, @(0x14,%0)  \n\t"
+                       "mov.l  r7, @(0x18,%0)  \n\t"
+                       "mov.l  r0, @(0x1c,%0)  \n\t"
+                       "bf.s   1b              \n\t"
+                       " add   #0x20, %0       \n\t"
+                       : "=&r" (data), "=&r" (len),
+                         "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4),
+                         "=&r" (tmp5), "=&r" (tmp6)
+                       : "r"(addr), "0" (data), "1" (len)
+                       : "r0", "r7", "t", "memory");
+       }
+
+       for (; len != 0; len--)
+               *data++ = ctrl_inl(addr);
+}
+EXPORT_SYMBOL(__raw_readsl);
+
+void __raw_writesl(unsigned long addr, const void *data, int len)
+{
+       if (likely(len != 0)) {
+               int tmp1;
+
+               __asm__ __volatile__ (
+                       "1:                             \n\t"
+                       "mov.l  @%0+, %1        \n\t"
+                       "dt             %3              \n\t"
+                       "bf.s           1b              \n\t"
+                       " mov.l %1, @%4         \n\t"
+                       : "=&r" (data), "=&r" (tmp1)
+                       : "0" (data), "r" (len), "r"(addr)
+                       : "t", "memory");
+       }
+}
+EXPORT_SYMBOL(__raw_writesl);
+
 void __iomem *ioport_map(unsigned long port, unsigned int nr)
 {
        return sh_mv.mv_ioport_map(port, nr);
index c2e07f7f3496a45efa79b87be2cc953b2ebd49e0..c7ebd6aec9514cdb4f16583a94a6570e01262440 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: irq.c,v 1.20 2004/01/13 05:52:11 kkojima Exp $
- *
+/*
  * linux/arch/sh/kernel/irq.c
  *
  *     Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
@@ -7,13 +6,15 @@
  *
  * SuperH version:  Copyright (C) 1999  Niibe Yutaka
  */
-
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/module.h>
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
 #include <asm/irq.h>
 #include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/thread_info.h>
 #include <asm/cpu/mmu_context.h>
 
 /*
@@ -60,15 +61,46 @@ unlock:
 }
 #endif
 
+#ifdef CONFIG_4KSTACKS
+/*
+ * per-CPU IRQ handling contexts (thread information and stack)
+ */
+union irq_ctx {
+       struct thread_info      tinfo;
+       u32                     stack[THREAD_SIZE/sizeof(u32)];
+};
+
+static union irq_ctx *hardirq_ctx[NR_CPUS];
+static union irq_ctx *softirq_ctx[NR_CPUS];
+#endif
 
 asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
                      unsigned long r6, unsigned long r7,
                      struct pt_regs regs)
 {
        int irq = r4;
+#ifdef CONFIG_4KSTACKS
+       union irq_ctx *curctx, *irqctx;
+#endif
 
        irq_enter();
 
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+       /* Debugging check for stack overflow: is there less than 1KB free? */
+       {
+               long sp;
+
+               __asm__ __volatile__ ("and r15, %0" :
+                                       "=r" (sp) : "0" (THREAD_SIZE - 1));
+
+               if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) {
+                       printk("do_IRQ: stack overflow: %ld\n",
+                              sp - sizeof(struct thread_info));
+                       dump_stack();
+               }
+       }
+#endif
+
 #ifdef CONFIG_CPU_HAS_INTEVT
        __asm__ __volatile__ (
 #ifdef CONFIG_CPU_HAS_SR_RB
@@ -87,7 +119,135 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
 #endif
 
        irq = irq_demux(irq);
-       __do_IRQ(irq, &regs);
+
+#ifdef CONFIG_4KSTACKS
+       curctx = (union irq_ctx *)current_thread_info();
+       irqctx = hardirq_ctx[smp_processor_id()];
+
+       /*
+        * this is where we switch to the IRQ stack. However, if we are
+        * already using the IRQ stack (because we interrupted a hardirq
+        * handler) we can't do that and just have to keep using the
+        * current stack (which is the irq stack already after all)
+        */
+       if (curctx != irqctx) {
+               u32 *isp;
+
+               isp = (u32 *)((char *)irqctx + sizeof(*irqctx));
+               irqctx->tinfo.task = curctx->tinfo.task;
+               irqctx->tinfo.previous_sp = current_stack_pointer;
+
+               __asm__ __volatile__ (
+                       "mov    %0, r4          \n"
+                       "mov    %1, r5          \n"
+                       "mov    r15, r9         \n"
+                       "jsr    @%2             \n"
+                       /* swith to the irq stack */
+                       " mov   %3, r15         \n"
+                       /* restore the stack (ring zero) */
+                       "mov    r9, r15         \n"
+                       : /* no outputs */
+                       : "r" (irq), "r" (&regs), "r" (__do_IRQ), "r" (isp)
+                       /* XXX: A somewhat excessive clobber list? -PFM */
+                       : "memory", "r0", "r1", "r2", "r3", "r4",
+                         "r5", "r6", "r7", "r8", "t", "pr"
+               );
+       } else
+#endif
+               __do_IRQ(irq, &regs);
+
        irq_exit();
+
        return 1;
 }
+
+#ifdef CONFIG_4KSTACKS
+/*
+ * These should really be __section__(".bss.page_aligned") as well, but
+ * gcc's 3.0 and earlier don't handle that correctly.
+ */
+static char softirq_stack[NR_CPUS * THREAD_SIZE]
+               __attribute__((__aligned__(THREAD_SIZE)));
+
+static char hardirq_stack[NR_CPUS * THREAD_SIZE]
+               __attribute__((__aligned__(THREAD_SIZE)));
+
+/*
+ * allocate per-cpu stacks for hardirq and for softirq processing
+ */
+void irq_ctx_init(int cpu)
+{
+       union irq_ctx *irqctx;
+
+       if (hardirq_ctx[cpu])
+               return;
+
+       irqctx = (union irq_ctx *)&hardirq_stack[cpu * THREAD_SIZE];
+       irqctx->tinfo.task              = NULL;
+       irqctx->tinfo.exec_domain       = NULL;
+       irqctx->tinfo.cpu               = cpu;
+       irqctx->tinfo.preempt_count     = HARDIRQ_OFFSET;
+       irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
+
+       hardirq_ctx[cpu] = irqctx;
+
+       irqctx = (union irq_ctx *)&softirq_stack[cpu * THREAD_SIZE];
+       irqctx->tinfo.task              = NULL;
+       irqctx->tinfo.exec_domain       = NULL;
+       irqctx->tinfo.cpu               = cpu;
+       irqctx->tinfo.preempt_count     = SOFTIRQ_OFFSET;
+       irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
+
+       softirq_ctx[cpu] = irqctx;
+
+       printk("CPU %u irqstacks, hard=%p soft=%p\n",
+               cpu, hardirq_ctx[cpu], softirq_ctx[cpu]);
+}
+
+void irq_ctx_exit(int cpu)
+{
+       hardirq_ctx[cpu] = NULL;
+}
+
+extern asmlinkage void __do_softirq(void);
+
+asmlinkage void do_softirq(void)
+{
+       unsigned long flags;
+       struct thread_info *curctx;
+       union irq_ctx *irqctx;
+       u32 *isp;
+
+       if (in_interrupt())
+               return;
+
+       local_irq_save(flags);
+
+       if (local_softirq_pending()) {
+               curctx = current_thread_info();
+               irqctx = softirq_ctx[smp_processor_id()];
+               irqctx->tinfo.task = curctx->task;
+               irqctx->tinfo.previous_sp = current_stack_pointer;
+
+               /* build the stack frame on the softirq stack */
+               isp = (u32 *)((char *)irqctx + sizeof(*irqctx));
+
+               __asm__ __volatile__ (
+                       "mov    r15, r9         \n"
+                       "jsr    @%0             \n"
+                       /* switch to the softirq stack */
+                       " mov   %1, r15         \n"
+                       /* restore the thread stack */
+                       "mov    r9, r15         \n"
+                       : /* no outputs */
+                       : "r" (__do_softirq), "r" (isp)
+                       /* XXX: A somewhat excessive clobber list? -PFM */
+                       : "memory", "r0", "r1", "r2", "r3", "r4",
+                         "r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
+               );
+       }
+
+       local_irq_restore(flags);
+}
+EXPORT_SYMBOL(do_softirq);
+#endif
index 42638b92b51c0828141e0937cf62a9a54a1d0307..9c6315f0335dfdc45bac2f8aa47a3fc9fa0adb11 100644 (file)
 #include <linux/linkage.h>
 #include <linux/init.h>
 
+#ifdef CONFIG_SH_KGDB_CONSOLE
+#include <linux/console.h>
+#endif
+
 #include <asm/system.h>
 #include <asm/current.h>
 #include <asm/signal.h>
 #include <asm/pgtable.h>
 #include <asm/ptrace.h>
 #include <asm/kgdb.h>
-
-#ifdef CONFIG_SH_KGDB_CONSOLE
-#include <linux/console.h>
-#endif
+#include <asm/io.h>
 
 /* Function pointers for linkage */
 kgdb_debug_hook_t *kgdb_debug_hook;
@@ -240,7 +241,6 @@ static jmp_buf rem_com_env;
 /* Misc static */
 static int stepped_address;
 static short stepped_opcode;
-static const char hexchars[] = "0123456789abcdef";
 static char in_buffer[BUFMAX];
 static char out_buffer[OUTBUFMAX];
 
@@ -253,29 +253,6 @@ typedef unsigned char threadref[8];
 #define BUF_THREAD_ID_SIZE 16
 #endif
 
-/* Return addr as a real volatile address */
-static inline unsigned int ctrl_inl(const unsigned long addr)
-{
-       return *(volatile unsigned long *) addr;
-}
-
-/* Correctly set *addr using volatile */
-static inline void ctrl_outl(const unsigned int b, unsigned long addr)
-{
-       *(volatile unsigned long *) addr = b;
-}
-
-/* Get high hex bits */
-static char highhex(const int x)
-{
-       return hexchars[(x >> 4) & 0xf];
-}
-
-/* Get low hex bits */
-static char lowhex(const int x)
-{
-       return hexchars[x & 0xf];
-}
 
 /* Convert ch to hex */
 static int hex(const char ch)
index 6bcd8d92399fcb094fa725831413e93b4a65f66f..08587cdb64d62577e481a19df5885f6b3dc1962b 100644 (file)
@@ -29,12 +29,6 @@ extern const unsigned char relocate_new_kernel[];
 extern const unsigned int relocate_new_kernel_size;
 extern void *gdb_vbr_vector;
 
-/*
- * Provide a dummy crash_notes definition while crash dump arrives to ppc.
- * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
- */
-void *crash_notes = NULL;
-
 void machine_shutdown(void)
 {
 }
diff --git a/arch/sh/kernel/pm.c b/arch/sh/kernel/pm.c
new file mode 100644 (file)
index 0000000..10ab62c
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Generic Power Management Routine
+ *
+ * Copyright (c) 2006 Andriy Skulysh <askulsyh@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License.
+ */
+#include <linux/suspend.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+#include <asm/freq.h>
+#include <asm/io.h>
+#include <asm/watchdog.h>
+#include <asm/pm.h>
+
+#define INTR_OFFSET    0x600
+
+#define STBCR          0xffffff82
+#define STBCR2         0xffffff88
+
+#define STBCR_STBY     0x80
+#define STBCR_MSTP2    0x04
+
+#define MCR            0xffffff68
+#define RTCNT          0xffffff70
+
+#define MCR_RMODE      2
+#define MCR_RFSH       4
+
+void pm_enter(void)
+{
+       u8 stbcr, csr;
+       u16 frqcr, mcr;
+       u32 vbr_new, vbr_old;
+
+       set_bl_bit();
+
+       /* set wdt */
+       csr = sh_wdt_read_csr();
+       csr &= ~WTCSR_TME;
+       csr |= WTCSR_CKS_4096;
+       sh_wdt_write_csr(csr);
+       csr = sh_wdt_read_csr();
+       sh_wdt_write_cnt(0);
+
+       /* disable PLL1 */
+       frqcr = ctrl_inw(FRQCR);
+       frqcr &= ~(FRQCR_PLLEN | FRQCR_PSTBY);
+       ctrl_outw(frqcr, FRQCR);
+
+       /* enable standby */
+       stbcr = ctrl_inb(STBCR);
+       ctrl_outb(stbcr | STBCR_STBY | STBCR_MSTP2, STBCR);
+
+       /* set self-refresh */
+       mcr = ctrl_inw(MCR);
+       ctrl_outw(mcr & ~MCR_RFSH, MCR);
+
+       /* set interrupt handler */
+       asm volatile("stc vbr, %0" : "=r" (vbr_old));
+       vbr_new = get_zeroed_page(GFP_ATOMIC);
+       udelay(50);
+       memcpy((void*)(vbr_new + INTR_OFFSET),
+              &wakeup_start, &wakeup_end - &wakeup_start);
+       asm volatile("ldc %0, vbr" : : "r" (vbr_new));
+
+       ctrl_outw(0, RTCNT);
+       ctrl_outw(mcr | MCR_RFSH | MCR_RMODE, MCR);
+
+       cpu_sleep();
+
+       asm volatile("ldc %0, vbr" : : "r" (vbr_old));
+
+       free_page(vbr_new);
+
+       /* enable PLL1 */
+       frqcr = ctrl_inw(FRQCR);
+       frqcr |= FRQCR_PSTBY;
+       ctrl_outw(frqcr, FRQCR);
+       udelay(50);
+       frqcr |= FRQCR_PLLEN;
+       ctrl_outw(frqcr, FRQCR);
+
+       ctrl_outb(stbcr, STBCR);
+
+       clear_bl_bit();
+}
index f2031314cb2b393c81b7599c36b393f6e323a3b4..0b1d5dd7a93b4237c70f3681d5745cac2296e3bd 100644 (file)
@@ -81,16 +81,6 @@ void cpu_idle(void)
 
 void machine_restart(char * __unused)
 {
-
-#ifdef CONFIG_KEXEC
-       struct kimage *image;
-       image = xchg(&kexec_image, 0);
-       if (image) {
-               machine_shutdown();
-               machine_kexec(image);
-       }
-#endif
-
        /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */
        asm volatile("ldc %0, sr\n\t"
                     "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001));
@@ -263,6 +253,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
                unsigned long unused,
                struct task_struct *p, struct pt_regs *regs)
 {
+       struct thread_info *ti = task_thread_info(p);
        struct pt_regs *childregs;
 #if defined(CONFIG_SH_FPU)
        struct task_struct *tsk = current;
@@ -277,8 +268,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 
        if (user_mode(regs)) {
                childregs->regs[15] = usp;
+               ti->addr_limit = USER_DS;
        } else {
                childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+               ti->addr_limit = KERNEL_DS;
        }
         if (clone_flags & CLONE_SETTLS) {
                childregs->gbr = childregs->regs[0];
@@ -299,13 +292,15 @@ ubc_set_tracing(int asid, unsigned long pc)
 {
        ctrl_outl(pc, UBC_BARA);
 
+#ifdef CONFIG_MMU
        /* We don't have any ASID settings for the SH-2! */
        if (cpu_data->type != CPU_SH7604)
                ctrl_outb(asid, UBC_BASRA);
+#endif
 
        ctrl_outl(0, UBC_BAMRA);
 
-       if (cpu_data->type == CPU_SH7729) {
+       if (cpu_data->type == CPU_SH7729 || cpu_data->type == CPU_SH7710) {
                ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA);
                ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR);
        } else {
@@ -344,6 +339,7 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
        }
 #endif
 
+#ifdef CONFIG_MMU
        /*
         * Restore the kernel mode register
         *      k7 (r7_bank1)
@@ -351,19 +347,21 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *ne
        asm volatile("ldc       %0, r7_bank"
                     : /* no output */
                     : "r" (task_thread_info(next)));
+#endif
 
-#ifdef CONFIG_MMU
        /* If no tasks are using the UBC, we're done */
        if (ubc_usercnt == 0)
                /* If no tasks are using the UBC, we're done */;
        else if (next->thread.ubc_pc && next->mm) {
-               ubc_set_tracing(next->mm->context & MMU_CONTEXT_ASID_MASK,
-                               next->thread.ubc_pc);
+               int asid = 0;
+#ifdef CONFIG_MMU
+               asid |= next->mm->context.id & MMU_CONTEXT_ASID_MASK;
+#endif
+               ubc_set_tracing(asid, next->thread.ubc_pc);
        } else {
                ctrl_outw(0, UBC_BBRA);
                ctrl_outw(0, UBC_BBRB);
        }
-#endif
 
        return prev;
 }
index f7eebbde329184808d7a4dfe955fb6756128f582..04ca13a041c160127077dddab6cfd507368fb319 100644 (file)
@@ -224,7 +224,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 
        case PTRACE_SETDSPREGS: {
                unsigned long dp;
-               int i;
 
                ret = -EIO;
                dp = ((unsigned long) child) + THREAD_SIZE -
index a3c24dcbf01ddb947adac9bbd0e23da516a29a30..184119eeae56add25f6f450e1a436f702637b45b 100644 (file)
@@ -14,7 +14,7 @@
 #include <asm/semaphore.h>
 #include <asm/semaphore-helper.h>
 
-spinlock_t semaphore_wake_lock;
+DEFINE_SPINLOCK(semaphore_wake_lock);
 
 /*
  * Semaphores are implemented using a two-way counter:
index e75189cb1db7ab29424da9cd40a27e462ddc6faf..5f587332234a3e977cf1203477831dddfb446f50 100644 (file)
@@ -43,27 +43,14 @@ extern void * __rd_start, * __rd_end;
  * The bigger value means no problem.
  */
 struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 10000000, };
+#ifdef CONFIG_VT
 struct screen_info screen_info;
+#endif
 
 #if defined(CONFIG_SH_UNKNOWN)
 struct sh_machine_vector sh_mv;
 #endif
 
-/* We need this to satisfy some external references. */
-struct screen_info screen_info = {
-        0, 25,                  /* orig-x, orig-y */
-        0,                      /* unused */
-        0,                      /* orig-video-page */
-        0,                      /* orig-video-mode */
-        80,                     /* orig-video-cols */
-        0,0,0,                  /* ega_ax, ega_bx, ega_cx */
-        25,                     /* orig-video-lines */
-        0,                      /* orig-video-isVGA */
-        16                      /* orig-video-points */
-};
-
-extern void platform_setup(void);
-extern char *get_system_type(void);
 extern int root_mountflags;
 
 #define MV_NAME_SIZE 32
@@ -90,29 +77,8 @@ static struct sh_machine_vector* __init get_mv_byname(const char* name);
 
 static char command_line[COMMAND_LINE_SIZE] = { 0, };
 
-struct resource standard_io_resources[] = {
-       { "dma1", 0x00, 0x1f },
-       { "pic1", 0x20, 0x3f },
-       { "timer", 0x40, 0x5f },
-       { "keyboard", 0x60, 0x6f },
-       { "dma page reg", 0x80, 0x8f },
-       { "pic2", 0xa0, 0xbf },
-       { "dma2", 0xc0, 0xdf },
-       { "fpu", 0xf0, 0xff }
-};
-
-#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource))
-
-/* System RAM - interrupted by the 640kB-1M hole */
-#define code_resource (ram_resources[3])
-#define data_resource (ram_resources[4])
-static struct resource ram_resources[] = {
-       { "System RAM", 0x000000, 0x09ffff, IORESOURCE_BUSY },
-       { "System RAM", 0x100000, 0x100000, IORESOURCE_BUSY },
-       { "Video RAM area", 0x0a0000, 0x0bffff },
-       { "Kernel code", 0x100000, 0 },
-       { "Kernel data", 0, 0 }
-};
+static struct resource code_resource = { .name = "Kernel code", };
+static struct resource data_resource = { .name = "Kernel data", };
 
 unsigned long memory_start, memory_end;
 
@@ -145,6 +111,24 @@ static inline void parse_cmdline (char ** cmdline_p, char mv_name[MV_NAME_SIZE],
                                memory_end = memory_start + mem_size;
                        }
                }
+
+#ifdef CONFIG_EARLY_PRINTK
+               if (c == ' ' && !memcmp(from, "earlyprintk=", 12)) {
+                       char *ep_end;
+
+                       if (to != command_line)
+                               to--;
+
+                       from += 12;
+                       ep_end = strchr(from, ' ');
+
+                       setup_early_printk(from);
+                       printk("early console enabled\n");
+
+                       from = ep_end;
+               }
+#endif
+
                if (c == ' ' && !memcmp(from, "sh_mv=", 6)) {
                        char* mv_end;
                        char* mv_comma;
@@ -237,6 +221,9 @@ static int __init sh_mv_setup(char **cmdline_p)
        __set_io_port_base(mv_io_base);
 #endif
 
+       if (!sh_mv.mv_nr_irqs)
+               sh_mv.mv_nr_irqs = NR_IRQS;
+
        return 0;
 }
 
@@ -245,11 +232,6 @@ void __init setup_arch(char **cmdline_p)
        unsigned long bootmap_size;
        unsigned long start_pfn, max_pfn, max_low_pfn;
 
-#ifdef CONFIG_EARLY_PRINTK
-       extern void enable_early_printk(void);
-
-       enable_early_printk();
-#endif
 #ifdef CONFIG_CMDLINE_BOOL
         strcpy(COMMAND_LINE, CONFIG_CMDLINE);
 #endif
@@ -368,14 +350,14 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
        /* Perform the machine specific initialisation */
-       platform_setup();
+       if (likely(sh_mv.mv_setup))
+               sh_mv.mv_setup(cmdline_p);
 
        paging_init();
 }
 
 struct sh_machine_vector* __init get_mv_byname(const char* name)
 {
-       extern int strcasecmp(const char *, const char *);
        extern long __machvec_start, __machvec_end;
        struct sh_machine_vector *all_vecs =
                (struct sh_machine_vector *)&__machvec_start;
@@ -410,25 +392,18 @@ static int __init topology_init(void)
 subsys_initcall(topology_init);
 
 static const char *cpu_name[] = {
-       [CPU_SH7604]    = "SH7604",
-       [CPU_SH7705]    = "SH7705",
-       [CPU_SH7708]    = "SH7708",
-       [CPU_SH7729]    = "SH7729",
-       [CPU_SH7300]    = "SH7300",
-       [CPU_SH7750]    = "SH7750",
-       [CPU_SH7750S]   = "SH7750S",
-       [CPU_SH7750R]   = "SH7750R",
-       [CPU_SH7751]    = "SH7751",
-       [CPU_SH7751R]   = "SH7751R",
-       [CPU_SH7760]    = "SH7760",
-       [CPU_SH73180]   = "SH73180",
-       [CPU_ST40RA]    = "ST40RA",
-       [CPU_ST40GX1]   = "ST40GX1",
-       [CPU_SH4_202]   = "SH4-202",
-       [CPU_SH4_501]   = "SH4-501",
-       [CPU_SH7770]    = "SH7770",
-       [CPU_SH7780]    = "SH7780",
-       [CPU_SH7781]    = "SH7781",
+       [CPU_SH7604]    = "SH7604",     [CPU_SH7300]    = "SH7300",
+       [CPU_SH7705]    = "SH7705",     [CPU_SH7706]    = "SH7706",
+       [CPU_SH7707]    = "SH7707",     [CPU_SH7708]    = "SH7708",
+       [CPU_SH7709]    = "SH7709",     [CPU_SH7710]    = "SH7710",
+       [CPU_SH7729]    = "SH7729",     [CPU_SH7750]    = "SH7750",
+       [CPU_SH7750S]   = "SH7750S",    [CPU_SH7750R]   = "SH7750R",
+       [CPU_SH7751]    = "SH7751",     [CPU_SH7751R]   = "SH7751R",
+       [CPU_SH7760]    = "SH7760",     [CPU_SH73180]   = "SH73180",
+       [CPU_ST40RA]    = "ST40RA",     [CPU_ST40GX1]   = "ST40GX1",
+       [CPU_SH4_202]   = "SH4-202",    [CPU_SH4_501]   = "SH4-501",
+       [CPU_SH7770]    = "SH7770",     [CPU_SH7780]    = "SH7780",
+       [CPU_SH7781]    = "SH7781",     [CPU_SH7343]    = "SH7343",
        [CPU_SH_NONE]   = "Unknown"
 };
 
@@ -438,8 +413,10 @@ const char *get_cpu_subtype(void)
 }
 
 #ifdef CONFIG_PROC_FS
+/* Symbolic CPU flags, keep in sync with asm/cpu-features.h */
 static const char *cpu_flags[] = {
-       "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr", "ptea", NULL
+       "none", "fpu", "p2flush", "mmuassoc", "dsp", "perfctr",
+       "ptea", "llsc", "l2", NULL
 };
 
 static void show_cpuflags(struct seq_file *m)
@@ -460,7 +437,8 @@ static void show_cpuflags(struct seq_file *m)
        seq_printf(m, "\n");
 }
 
-static void show_cacheinfo(struct seq_file *m, const char *type, struct cache_info info)
+static void show_cacheinfo(struct seq_file *m, const char *type,
+                          struct cache_info info)
 {
        unsigned int cache_size;
 
@@ -493,7 +471,7 @@ 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 (test_bit(SH_CACHE_COMBINED, &(boot_cpu_data.icache.flags))) {
+       if (boot_cpu_data.icache.flags & SH_CACHE_COMBINED) {
                seq_printf(m, "unified\n");
                show_cacheinfo(m, "cache", boot_cpu_data.icache);
        } else {
@@ -502,6 +480,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                show_cacheinfo(m, "dcache", boot_cpu_data.dcache);
        }
 
+       /* Optional secondary cache */
+       if (boot_cpu_data.flags & CPU_HAS_L2_CACHE)
+               show_cacheinfo(m, "scache", boot_cpu_data.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);
@@ -617,4 +599,3 @@ static int __init kgdb_parse_options(char *options)
 }
 __setup("kgdb=", kgdb_parse_options);
 #endif /* CONFIG_SH_KGDB */
-
index 245ed8f945e8e705b72b1db956f9a5e40ada2e36..d3cbfa2ad4a785b13d9e6b130ee5c435b9cbf948 100644 (file)
@@ -27,21 +27,11 @@ EXPORT_SYMBOL(sh_mv);
 
 /* platform dependent support */
 EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(enable_irq);
-EXPORT_SYMBOL(disable_irq);
-EXPORT_SYMBOL(probe_irq_mask);
 EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(disable_irq_nosync);
 EXPORT_SYMBOL(irq_desc);
 EXPORT_SYMBOL(no_irq_type);
 
-EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strchr);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strncat);
 
 /* PCI exports */
 #ifdef CONFIG_PCI
@@ -52,13 +42,8 @@ EXPORT_SYMBOL(pci_free_consistent);
 /* mem exports */
 EXPORT_SYMBOL(memchr);
 EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(memcpy_fromio);
-EXPORT_SYMBOL(memcpy_toio);
 EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(memset_io);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(memcmp);
-EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(__copy_user);
 EXPORT_SYMBOL(boot_cpu_data);
 
@@ -94,7 +79,9 @@ EXPORT_SYMBOL(strcpy);
 DECLARE_EXPORT(__movstr_i4_even);
 DECLARE_EXPORT(__movstr_i4_odd);
 DECLARE_EXPORT(__movstrSI12_i4);
+#endif
 
+#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
 /* needed by some modules */
 EXPORT_SYMBOL(flush_cache_all);
 EXPORT_SYMBOL(flush_cache_range);
@@ -102,11 +89,9 @@ EXPORT_SYMBOL(flush_dcache_page);
 EXPORT_SYMBOL(__flush_purge_region);
 #endif
 
-#if defined(CONFIG_SH7705_CACHE_32KB)
-EXPORT_SYMBOL(flush_cache_all);
-EXPORT_SYMBOL(flush_cache_range);
-EXPORT_SYMBOL(flush_dcache_page);
-EXPORT_SYMBOL(__flush_purge_region);
+#if defined(CONFIG_MMU) && (defined(CONFIG_CPU_SH4) || \
+       defined(CONFIG_SH7705_CACHE_32KB))
+EXPORT_SYMBOL(clear_user_page);
 #endif
 
 EXPORT_SYMBOL(flush_tlb_page);
@@ -116,7 +101,12 @@ EXPORT_SYMBOL(__down_trylock);
 EXPORT_SYMBOL(synchronize_irq);
 #endif
 
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(pm_suspend);
+#endif
+
 EXPORT_SYMBOL(csum_partial);
+#ifdef CONFIG_IPV6
 EXPORT_SYMBOL(csum_ipv6_magic);
-EXPORT_SYMBOL(consistent_sync);
+#endif
 EXPORT_SYMBOL(clear_page);
index b475c4d2405f3e81795dfb39dfdd8aa2c350e94d..5213f5bc6ce0832c395f5b69f4eeacf407a41479 100644 (file)
@@ -8,7 +8,6 @@
  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
  *
  */
-
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -21,6 +20,7 @@
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/tty.h>
+#include <linux/elf.h>
 #include <linux/personality.h>
 #include <linux/binfmts.h>
 
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 
-#define DEBUG_SIG 0
-
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -43,51 +39,17 @@ sys_sigsuspend(old_sigset_t mask,
               unsigned long r5, unsigned long r6, unsigned long r7,
               struct pt_regs regs)
 {
-       sigset_t saveset;
-
        mask &= _BLOCKABLE;
        spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
+       current->saved_sigmask = current->blocked;
        siginitset(&current->blocked, mask);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       regs.regs[0] = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(&regs, &saveset))
-                       return -EINTR;
-       }
-}
-
-asmlinkage int
-sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
-                 unsigned long r6, unsigned long r7,
-                 struct pt_regs regs)
-{
-       sigset_t saveset, newset;
-
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
-
-       if (copy_from_user(&newset, unewset, sizeof(newset)))
-               return -EFAULT;
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       regs.regs[0] = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(&regs, &saveset))
-                       return -EINTR;
-       }
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_thread_flag(TIF_RESTORE_SIGMASK);
+       return -ERESTARTNOHAND;
 }
 
 asmlinkage int 
@@ -348,7 +310,12 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
        return (void __user *)((sp - frame_size) & -8ul);
 }
 
-static void setup_frame(int sig, struct k_sigaction *ka,
+/* These symbols are defined with the addresses in the vsyscall page.
+   See vsyscall-trapa.S.  */
+extern void __user __kernel_sigreturn;
+extern void __user __kernel_rt_sigreturn;
+
+static int setup_frame(int sig, struct k_sigaction *ka,
                        sigset_t *set, struct pt_regs *regs)
 {
        struct sigframe __user *frame;
@@ -368,15 +335,18 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 
        err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
 
-       if (_NSIG_WORDS > 1) {
+       if (_NSIG_WORDS > 1)
                err |= __copy_to_user(frame->extramask, &set->sig[1],
                                      sizeof(frame->extramask));
-       }
 
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
        if (ka->sa.sa_flags & SA_RESTORER) {
                regs->pr = (unsigned long) ka->sa.sa_restorer;
+#ifdef CONFIG_VSYSCALL
+       } else if (likely(current->mm->context.vdso)) {
+               regs->pr = VDSO_SYM(&__kernel_sigreturn);
+#endif
        } else {
                /* Generate return code (system call to sigreturn) */
                err |= __put_user(MOVW(7), &frame->retcode[0]);
@@ -402,21 +372,22 @@ static void setup_frame(int sig, struct k_sigaction *ka,
 
        set_fs(USER_DS);
 
-#if DEBUG_SIG
-       printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
-               current->comm, current->pid, frame, regs->pc, regs->pr);
-#endif
+       pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
+                current->comm, current->pid, frame, regs->pc, regs->pr);
 
        flush_cache_sigtramp(regs->pr);
+
        if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
                flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
-       return;
+
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                           sigset_t *set, struct pt_regs *regs)
 {
        struct rt_sigframe __user *frame;
@@ -452,6 +423,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
           already in userspace.  */
        if (ka->sa.sa_flags & SA_RESTORER) {
                regs->pr = (unsigned long) ka->sa.sa_restorer;
+#ifdef CONFIG_VSYSCALL
+       } else if (likely(current->mm->context.vdso)) {
+               regs->pr = VDSO_SYM(&__kernel_rt_sigreturn);
+#endif
        } else {
                /* Generate return code (system call to rt_sigreturn) */
                err |= __put_user(MOVW(7), &frame->retcode[0]);
@@ -477,28 +452,31 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        set_fs(USER_DS);
 
-#if DEBUG_SIG
-       printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
-               current->comm, current->pid, frame, regs->pc, regs->pr);
-#endif
+       pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
+                current->comm, current->pid, frame, regs->pc, regs->pr);
 
        flush_cache_sigtramp(regs->pr);
+
        if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
                flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
-       return;
+
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
 /*
  * OK, we're invoking a handler
  */
 
-static void
+static int
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
              sigset_t *oldset, struct pt_regs *regs)
 {
+       int ret;
+
        /* Are we from a system call? */
        if (regs->tra >= 0) {
                /* If so, check system call restarting.. */
@@ -539,19 +517,23 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
-               setup_rt_frame(sig, ka, info, oldset, regs);
+               ret = setup_rt_frame(sig, ka, info, oldset, regs);
        else
-               setup_frame(sig, ka, oldset, regs);
+               ret = setup_frame(sig, ka, oldset, regs);
 
        if (ka->sa.sa_flags & SA_ONESHOT)
                ka->sa.sa_handler = SIG_DFL;
 
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&current->blocked,sig);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       if (ret == 0) {
+               spin_lock_irq(&current->sighand->siglock);
+               sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked,sig);
+               recalc_sigpending();
+               spin_unlock_irq(&current->sighand->siglock);
+       }
+
+       return ret;
 }
 
 /*
@@ -563,11 +545,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void do_signal(struct pt_regs *regs, unsigned int save_r0)
 {
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
+       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -576,19 +559,27 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
         * if so.
         */
        if (!user_mode(regs))
-               return 1;
+               return;
 
        if (try_to_freeze())
                goto no_signal;
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
-               handle_signal(signr, &ka, &info, oldset, regs);
-               return 1;
+               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+                       /* a signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TIF_RESTORE_SIGMASK flag */
+                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               }
        }
 
  no_signal:
@@ -597,10 +588,27 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                /* Restart the system call - no handlers present */
                if (regs->regs[0] == -ERESTARTNOHAND ||
                    regs->regs[0] == -ERESTARTSYS ||
-                   regs->regs[0] == -ERESTARTNOINTR ||
-                   regs->regs[0] == -ERESTART_RESTARTBLOCK) {
+                   regs->regs[0] == -ERESTARTNOINTR) {
+                       regs->regs[0] = save_r0;
+                       regs->pc -= 2;
+               } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
                        regs->pc -= 2;
+                       regs->regs[3] = __NR_restart_syscall;
                }
        }
-       return 0;
+
+       /* if there's no signal to deliver, we just put the saved sigmask
+        * back */
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
+}
+
+asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,
+                                __u32 thread_info_flags)
+{
+       /* deal with pending signal delivery */
+       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+               do_signal(regs, save_r0);
 }
index 917b2f32f260888b2a84b272303edce8d0b5c1b6..b68ff705f0673c56c1a6845d97569689df136932 100644 (file)
@@ -21,7 +21,8 @@
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
-
+#include <linux/module.h>
+#include <asm/cacheflush.h>
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
 
@@ -44,11 +45,16 @@ asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
        return error;
 }
 
-#if defined(HAVE_ARCH_UNMAPPED_AREA)
+unsigned long shm_align_mask = PAGE_SIZE - 1;  /* Sane caches */
+
+EXPORT_SYMBOL(shm_align_mask);
+
 /*
- * To avoid cache alias, we map the shard page with same color.
+ * To avoid cache aliases, we map the shared page with same color.
  */
-#define COLOUR_ALIGN(addr)     (((addr)+SHMLBA-1)&~(SHMLBA-1))
+#define COLOUR_ALIGN(addr, pgoff)                              \
+       ((((addr) + shm_align_mask) & ~shm_align_mask) +        \
+        (((pgoff) << PAGE_SHIFT) & shm_align_mask))
 
 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
        unsigned long len, unsigned long pgoff, unsigned long flags)
@@ -56,43 +62,52 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
        unsigned long start_addr;
+       int do_colour_align;
 
        if (flags & MAP_FIXED) {
                /* We do not accept a shared mapping if it would violate
                 * cache aliasing constraints.
                 */
-               if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
+               if ((flags & MAP_SHARED) && (addr & shm_align_mask))
                        return -EINVAL;
                return addr;
        }
 
-       if (len > TASK_SIZE)
+       if (unlikely(len > TASK_SIZE))
                return -ENOMEM;
 
+       do_colour_align = 0;
+       if (filp || (flags & MAP_SHARED))
+               do_colour_align = 1;
+
        if (addr) {
-               if (flags & MAP_PRIVATE)
-                       addr = PAGE_ALIGN(addr);
+               if (do_colour_align)
+                       addr = COLOUR_ALIGN(addr, pgoff);
                else
-                       addr = COLOUR_ALIGN(addr);
+                       addr = PAGE_ALIGN(addr);
+
                vma = find_vma(mm, addr);
                if (TASK_SIZE - len >= addr &&
                    (!vma || addr + len <= vma->vm_start))
                        return addr;
        }
-       if (len <= mm->cached_hole_size) {
+
+       if (len > mm->cached_hole_size) {
+               start_addr = addr = mm->free_area_cache;
+       } else {
                mm->cached_hole_size = 0;
-               mm->free_area_cache = TASK_UNMAPPED_BASE;
+               start_addr = addr = TASK_UNMAPPED_BASE;
        }
-       if (flags & MAP_PRIVATE)
-               addr = PAGE_ALIGN(mm->free_area_cache);
-       else
-               addr = COLOUR_ALIGN(mm->free_area_cache);
-       start_addr = addr;
 
 full_search:
+       if (do_colour_align)
+               addr = COLOUR_ALIGN(addr, pgoff);
+       else
+               addr = PAGE_ALIGN(mm->free_area_cache);
+
        for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
                /* At this point:  (!vma || addr < vma->vm_end). */
-               if (TASK_SIZE - len < addr) {
+               if (unlikely(TASK_SIZE - len < addr)) {
                        /*
                         * Start a new search - just in case we missed
                         * some holes.
@@ -104,7 +119,7 @@ full_search:
                        }
                        return -ENOMEM;
                }
-               if (!vma || addr + len <= vma->vm_start) {
+               if (likely(!vma || addr + len <= vma->vm_start)) {
                        /*
                         * Remember the place where we stopped the search:
                         */
@@ -115,11 +130,10 @@ full_search:
                        mm->cached_hole_size = vma->vm_start - addr;
 
                addr = vma->vm_end;
-               if (!(flags & MAP_PRIVATE))
-                       addr = COLOUR_ALIGN(addr);
+               if (do_colour_align)
+                       addr = COLOUR_ALIGN(addr, pgoff);
        }
 }
-#endif
 
 static inline long
 do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, 
diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S
new file mode 100644 (file)
index 0000000..768334e
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * arch/sh/kernel/syscalls.S
+ *
+ * System call table for SuperH
+ *
+ *  Copyright (C) 1999, 2000, 2002  Niibe Yutaka
+ *  Copyright (C) 2003  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_NFSD) && !defined(CONFIG_NFSD_MODULE)
+#define sys_nfsservctl         sys_ni_syscall
+#endif
+
+#if !defined(CONFIG_MMU)
+#define sys_madvise            sys_ni_syscall
+#define sys_readahead          sys_ni_syscall
+#define sys_mprotect           sys_ni_syscall
+#define sys_msync              sys_ni_syscall
+#define sys_mlock              sys_ni_syscall
+#define sys_munlock            sys_ni_syscall
+#define sys_mlockall           sys_ni_syscall
+#define sys_munlockall         sys_ni_syscall
+#define sys_mremap             sys_ni_syscall
+#define sys_mincore            sys_ni_syscall
+#define sys_remap_file_pages   sys_ni_syscall
+#endif
+
+       .data
+ENTRY(sys_call_table)
+       .long sys_restart_syscall       /* 0  -  old "setup()" system call*/
+       .long sys_exit
+       .long sys_fork
+       .long sys_read
+       .long sys_write
+       .long sys_open          /* 5 */
+       .long sys_close
+       .long sys_waitpid
+       .long sys_creat
+       .long sys_link
+       .long sys_unlink                /* 10 */
+       .long sys_execve
+       .long sys_chdir
+       .long sys_time
+       .long sys_mknod
+       .long sys_chmod         /* 15 */
+       .long sys_lchown16
+       .long sys_ni_syscall    /* old break syscall holder */
+       .long sys_stat
+       .long sys_lseek
+       .long sys_getpid                /* 20 */
+       .long sys_mount
+       .long sys_oldumount
+       .long sys_setuid16
+       .long sys_getuid16
+       .long sys_stime         /* 25 */
+       .long sys_ptrace
+       .long sys_alarm
+       .long sys_fstat
+       .long sys_pause
+       .long sys_utime         /* 30 */
+       .long sys_ni_syscall    /* old stty syscall holder */
+       .long sys_ni_syscall    /* old gtty syscall holder */
+       .long sys_access
+       .long sys_nice
+       .long sys_ni_syscall    /* 35 */                /* old ftime syscall holder */
+       .long sys_sync
+       .long sys_kill
+       .long sys_rename
+       .long sys_mkdir
+       .long sys_rmdir         /* 40 */
+       .long sys_dup
+       .long sys_pipe
+       .long sys_times
+       .long sys_ni_syscall    /* old prof syscall holder */
+       .long sys_brk           /* 45 */
+       .long sys_setgid16
+       .long sys_getgid16
+       .long sys_signal
+       .long sys_geteuid16
+       .long sys_getegid16     /* 50 */
+       .long sys_acct
+       .long sys_umount                /* recycled never used phys() */
+       .long sys_ni_syscall    /* old lock syscall holder */
+       .long sys_ioctl
+       .long sys_fcntl         /* 55 */
+       .long sys_ni_syscall    /* old mpx syscall holder */
+       .long sys_setpgid
+       .long sys_ni_syscall    /* old ulimit syscall holder */
+       .long sys_ni_syscall    /* sys_olduname */
+       .long sys_umask         /* 60 */
+       .long sys_chroot
+       .long sys_ustat
+       .long sys_dup2
+       .long sys_getppid
+       .long sys_getpgrp               /* 65 */
+       .long sys_setsid
+       .long sys_sigaction
+       .long sys_sgetmask
+       .long sys_ssetmask
+       .long sys_setreuid16    /* 70 */
+       .long sys_setregid16
+       .long sys_sigsuspend
+       .long sys_sigpending
+       .long sys_sethostname
+       .long sys_setrlimit     /* 75 */
+       .long sys_old_getrlimit
+       .long sys_getrusage
+       .long sys_gettimeofday
+       .long sys_settimeofday
+       .long sys_getgroups16   /* 80 */
+       .long sys_setgroups16
+       .long sys_ni_syscall    /* sys_oldselect */
+       .long sys_symlink
+       .long sys_lstat
+       .long sys_readlink              /* 85 */
+       .long sys_uselib
+       .long sys_swapon
+       .long sys_reboot
+       .long old_readdir
+       .long old_mmap          /* 90 */
+       .long sys_munmap
+       .long sys_truncate
+       .long sys_ftruncate
+       .long sys_fchmod
+       .long sys_fchown16              /* 95 */
+       .long sys_getpriority
+       .long sys_setpriority
+       .long sys_ni_syscall    /* old profil syscall holder */
+       .long sys_statfs
+       .long sys_fstatfs               /* 100 */
+       .long sys_ni_syscall    /* ioperm */
+       .long sys_socketcall
+       .long sys_syslog
+       .long sys_setitimer
+       .long sys_getitimer     /* 105 */
+       .long sys_newstat
+       .long sys_newlstat
+       .long sys_newfstat
+       .long sys_uname
+       .long sys_ni_syscall    /* 110 */ /* iopl */
+       .long sys_vhangup
+       .long sys_ni_syscall    /* idle */
+       .long sys_ni_syscall    /* vm86old */
+       .long sys_wait4
+       .long sys_swapoff               /* 115 */
+       .long sys_sysinfo
+       .long sys_ipc
+       .long sys_fsync
+       .long sys_sigreturn
+       .long sys_clone         /* 120 */
+       .long sys_setdomainname
+       .long sys_newuname
+       .long sys_ni_syscall    /* sys_modify_ldt */
+       .long sys_adjtimex
+       .long sys_mprotect              /* 125 */
+       .long sys_sigprocmask
+       .long sys_ni_syscall    /* old "create_module" */
+       .long sys_init_module
+       .long sys_delete_module
+       .long sys_ni_syscall    /* 130: old "get_kernel_syms" */
+       .long sys_quotactl
+       .long sys_getpgid
+       .long sys_fchdir
+       .long sys_bdflush
+       .long sys_sysfs         /* 135 */
+       .long sys_personality
+       .long sys_ni_syscall    /* for afs_syscall */
+       .long sys_setfsuid16
+       .long sys_setfsgid16
+       .long sys_llseek                /* 140 */
+       .long sys_getdents
+       .long sys_select
+       .long sys_flock
+       .long sys_msync
+       .long sys_readv         /* 145 */
+       .long sys_writev
+       .long sys_getsid
+       .long sys_fdatasync
+       .long sys_sysctl
+       .long sys_mlock         /* 150 */
+       .long sys_munlock
+       .long sys_mlockall
+       .long sys_munlockall
+       .long sys_sched_setparam
+       .long sys_sched_getparam   /* 155 */
+       .long sys_sched_setscheduler
+       .long sys_sched_getscheduler
+       .long sys_sched_yield
+       .long sys_sched_get_priority_max
+       .long sys_sched_get_priority_min  /* 160 */
+       .long sys_sched_rr_get_interval
+       .long sys_nanosleep
+       .long sys_mremap
+       .long sys_setresuid16
+       .long sys_getresuid16   /* 165 */
+       .long sys_ni_syscall    /* vm86 */
+       .long sys_ni_syscall    /* old "query_module" */
+       .long sys_poll
+       .long sys_nfsservctl
+       .long sys_setresgid16   /* 170 */
+       .long sys_getresgid16
+       .long sys_prctl
+       .long sys_rt_sigreturn
+       .long sys_rt_sigaction
+       .long sys_rt_sigprocmask        /* 175 */
+       .long sys_rt_sigpending
+       .long sys_rt_sigtimedwait
+       .long sys_rt_sigqueueinfo
+       .long sys_rt_sigsuspend
+       .long sys_pread_wrapper    /* 180 */
+       .long sys_pwrite_wrapper
+       .long sys_chown16
+       .long sys_getcwd
+       .long sys_capget
+       .long sys_capset           /* 185 */
+       .long sys_sigaltstack
+       .long sys_sendfile
+       .long sys_ni_syscall    /* streams1 */
+       .long sys_ni_syscall    /* streams2 */
+       .long sys_vfork            /* 190 */
+       .long sys_getrlimit
+       .long sys_mmap2
+       .long sys_truncate64
+       .long sys_ftruncate64
+       .long sys_stat64                /* 195 */
+       .long sys_lstat64
+       .long sys_fstat64
+       .long sys_lchown
+       .long sys_getuid
+       .long sys_getgid                /* 200 */
+       .long sys_geteuid
+       .long sys_getegid
+       .long sys_setreuid
+       .long sys_setregid
+       .long sys_getgroups     /* 205 */
+       .long sys_setgroups
+       .long sys_fchown
+       .long sys_setresuid
+       .long sys_getresuid
+       .long sys_setresgid     /* 210 */
+       .long sys_getresgid
+       .long sys_chown
+       .long sys_setuid
+       .long sys_setgid
+       .long sys_setfsuid              /* 215 */
+       .long sys_setfsgid
+       .long sys_pivot_root
+       .long sys_mincore
+       .long sys_madvise
+       .long sys_getdents64    /* 220 */
+       .long sys_fcntl64
+       .long sys_ni_syscall    /* reserved for TUX */
+       .long sys_ni_syscall    /* Reserved for Security */
+       .long sys_gettid
+       .long sys_readahead     /* 225 */
+       .long sys_setxattr
+       .long sys_lsetxattr
+       .long sys_fsetxattr
+       .long sys_getxattr
+       .long sys_lgetxattr     /* 230 */
+       .long sys_fgetxattr
+       .long sys_listxattr
+       .long sys_llistxattr
+       .long sys_flistxattr
+       .long sys_removexattr   /* 235 */
+       .long sys_lremovexattr
+       .long sys_fremovexattr
+       .long sys_tkill
+       .long sys_sendfile64
+       .long sys_futex         /* 240 */
+       .long sys_sched_setaffinity
+       .long sys_sched_getaffinity
+       .long sys_ni_syscall
+       .long sys_ni_syscall
+       .long sys_io_setup      /* 245 */
+       .long sys_io_destroy
+       .long sys_io_getevents
+       .long sys_io_submit
+       .long sys_io_cancel
+       .long sys_fadvise64     /* 250 */
+       .long sys_ni_syscall
+       .long sys_exit_group
+       .long sys_lookup_dcookie
+       .long sys_epoll_create
+       .long sys_epoll_ctl     /* 255 */
+       .long sys_epoll_wait
+       .long sys_remap_file_pages
+       .long sys_set_tid_address
+       .long sys_timer_create
+       .long sys_timer_settime         /* 260 */
+       .long sys_timer_gettime
+       .long sys_timer_getoverrun
+       .long sys_timer_delete
+       .long sys_clock_settime
+       .long sys_clock_gettime         /* 265 */
+       .long sys_clock_getres
+       .long sys_clock_nanosleep
+       .long sys_statfs64
+       .long sys_fstatfs64
+       .long sys_tgkill                /* 270 */
+       .long sys_utimes
+       .long sys_fadvise64_64_wrapper
+       .long sys_ni_syscall    /* Reserved for vserver */
+       .long sys_ni_syscall    /* Reserved for mbind */
+       .long sys_ni_syscall    /* 275 - get_mempolicy */
+       .long sys_ni_syscall    /* set_mempolicy */
+       .long sys_mq_open
+       .long sys_mq_unlink
+       .long sys_mq_timedsend
+       .long sys_mq_timedreceive       /* 280 */
+       .long sys_mq_notify
+       .long sys_mq_getsetattr
+       .long sys_kexec_load
+       .long sys_waitid
+       .long sys_ni_syscall            /* 285 */
+       .long sys_add_key
+       .long sys_request_key
+       .long sys_keyctl
+       .long sys_ioprio_set
+       .long sys_ioprio_get            /* 290 */
+       .long sys_inotify_init
+       .long sys_inotify_add_watch
+       .long sys_inotify_rm_watch
+       .long sys_migrate_pages
+       .long sys_openat                /* 295 */
+       .long sys_mkdirat
+       .long sys_mknodat
+       .long sys_fchownat
+       .long sys_futimesat
+       .long sys_fstatat64             /* 300 */
+       .long sys_unlinkat
+       .long sys_renameat
+       .long sys_linkat
+       .long sys_symlinkat
+       .long sys_readlinkat            /* 305 */
+       .long sys_fchmodat
+       .long sys_faccessat
+       .long sys_pselect6
+       .long sys_ppoll
+       .long sys_unshare               /* 310 */
+       .long sys_set_robust_list
+       .long sys_get_robust_list
+       .long sys_splice
+       .long sys_sync_file_range
+       .long sys_tee                   /* 315 */
+       .long sys_vmsplice
index a1589f85499dc58323f5785d7848178f18c3b3ea..149d9713eddf0432ff8321972cd31320652f4c30 100644 (file)
@@ -3,13 +3,12 @@
  *
  *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
- *  Copyright (C) 2002, 2003, 2004, 2005  Paul Mundt
+ *  Copyright (C) 2002 - 2006  Paul Mundt
  *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
  *
  *  Some code taken from i386 version.
  *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
  */
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -26,15 +25,20 @@ struct sys_timer *sys_timer;
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 
-/* XXX: Can we initialize this in a routine somewhere?  Dreamcast doesn't want
- * these routines anywhere... */
-#ifdef CONFIG_SH_RTC
-void (*rtc_get_time)(struct timespec *) = sh_rtc_gettimeofday;
-int (*rtc_set_time)(const time_t) = sh_rtc_settimeofday;
-#else
-void (*rtc_get_time)(struct timespec *);
-int (*rtc_set_time)(const time_t);
-#endif
+/* Dummy RTC ops */
+static void null_rtc_get_time(struct timespec *tv)
+{
+       tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0);
+       tv->tv_nsec = 0;
+}
+
+static int null_rtc_set_time(const time_t secs)
+{
+       return 0;
+}
+
+void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time;
+int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time;
 
 /*
  * Scheduler clock - returns current time in nanosec units.
@@ -70,7 +74,6 @@ void do_gettimeofday(struct timeval *tv)
        tv->tv_sec = sec;
        tv->tv_usec = usec;
 }
-
 EXPORT_SYMBOL(do_gettimeofday);
 
 int do_settimeofday(struct timespec *tv)
@@ -103,7 +106,6 @@ int do_settimeofday(struct timespec *tv)
 
        return 0;
 }
-
 EXPORT_SYMBOL(do_settimeofday);
 
 /* last time the RTC clock got updated */
@@ -135,7 +137,7 @@ void handle_timer_tick(struct pt_regs *regs)
            xtime.tv_sec > last_rtc_update + 660 &&
            (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
            (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) {
-               if (rtc_set_time(xtime.tv_sec) == 0)
+               if (rtc_sh_set_time(xtime.tv_sec) == 0)
                        last_rtc_update = xtime.tv_sec;
                else
                        /* do it again in 60s */
@@ -143,8 +145,33 @@ void handle_timer_tick(struct pt_regs *regs)
        }
 }
 
+#ifdef CONFIG_PM
+int timer_suspend(struct sys_device *dev, pm_message_t state)
+{
+       struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev);
+
+       sys_timer->ops->stop();
+
+       return 0;
+}
+
+int timer_resume(struct sys_device *dev)
+{
+       struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev);
+
+       sys_timer->ops->start();
+
+       return 0;
+}
+#else
+#define timer_suspend NULL
+#define timer_resume NULL
+#endif
+
 static struct sysdev_class timer_sysclass = {
        set_kset_name("timer"),
+       .suspend = timer_suspend,
+       .resume  = timer_resume,
 };
 
 static int __init timer_init_sysfs(void)
@@ -156,7 +183,6 @@ static int __init timer_init_sysfs(void)
        sys_timer->dev.cls = &timer_sysclass;
        return sysdev_register(&sys_timer->dev);
 }
-
 device_initcall(timer_init_sysfs);
 
 void (*board_time_init)(void);
@@ -168,15 +194,9 @@ void __init time_init(void)
 
        clk_init();
 
-       if (rtc_get_time) {
-               rtc_get_time(&xtime);
-       } else {
-               xtime.tv_sec = mktime(2000, 1, 1, 0, 0, 0);
-               xtime.tv_nsec = 0;
-       }
-
-        set_normalized_timespec(&wall_to_monotonic,
-                                -xtime.tv_sec, -xtime.tv_nsec);
+       rtc_sh_get_time(&xtime);
+       set_normalized_timespec(&wall_to_monotonic,
+                               -xtime.tv_sec, -xtime.tv_nsec);
 
        /*
         * Find the timer to use as the system timer, it will be
index d4212add53b264094c0261d12011bc610bd6d978..205816fcf0da50d7fecdeecd5975c2fbaf6c0a9e 100644 (file)
@@ -132,17 +132,17 @@ static unsigned long tmu_timer_get_frequency(void)
        ctrl_outl(0xffffffff, TMU0_TCOR);
        ctrl_outl(0xffffffff, TMU0_TCNT);
 
-       rtc_get_time(&ts2);
+       rtc_sh_get_time(&ts2);
 
        do {
-               rtc_get_time(&ts1);
+               rtc_sh_get_time(&ts1);
        } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
 
        /* actually start the timer */
        ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
 
        do {
-               rtc_get_time(&ts2);
+               rtc_sh_get_time(&ts2);
        } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec);
 
        freq = 0xffffffff - ctrl_inl(TMU0_TCNT);
@@ -188,6 +188,18 @@ static struct clk tmu0_clk = {
        .ops            = &tmu_clk_ops,
 };
 
+static int tmu_timer_start(void)
+{
+       ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+       return 0;
+}
+
+static int tmu_timer_stop(void)
+{
+       ctrl_outb(0, TMU_TSTR);
+       return 0;
+}
+
 static int tmu_timer_init(void)
 {
        unsigned long interval;
@@ -197,7 +209,7 @@ static int tmu_timer_init(void)
        tmu0_clk.parent = clk_get("module_clk");
 
        /* Start TMU0 */
-       ctrl_outb(0, TMU_TSTR);
+       tmu_timer_stop();
 #if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760)
        ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
 #endif
@@ -211,13 +223,15 @@ static int tmu_timer_init(void)
        ctrl_outl(interval, TMU0_TCOR);
        ctrl_outl(interval, TMU0_TCNT);
 
-       ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
+       tmu_timer_start();
 
        return 0;
 }
 
 struct sys_timer_ops tmu_timer_ops = {
        .init           = tmu_timer_init,
+       .start          = tmu_timer_start,
+       .stop           = tmu_timer_stop,
        .get_frequency  = tmu_timer_get_frequency,
        .get_offset     = tmu_timer_get_offset,
 };
index d9db1180f770faa264b561a3f20c14e32d1b671b..c2c597e0948242c780d4d369dff64c69dee14c59 100644 (file)
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
-#define CHK_REMOTE_DEBUG(regs)                                               \
-{                                                                            \
-  if ((kgdb_debug_hook != (kgdb_debug_hook_t *) NULL) && (!user_mode(regs))) \
-  {                                                                          \
-    (*kgdb_debug_hook)(regs);                                                \
-  }                                                                          \
+#define CHK_REMOTE_DEBUG(regs)                         \
+{                                              \
+       if (kgdb_debug_hook && !user_mode(regs))\
+               (*kgdb_debug_hook)(regs);       \
 }
 #else
 #define CHK_REMOTE_DEBUG(regs)
 #endif
 
-#define DO_ERROR(trapnr, signr, str, name, tsk)                                \
-asmlinkage void do_##name(unsigned long r4, unsigned long r5,          \
-                         unsigned long r6, unsigned long r7,           \
-                         struct pt_regs regs)                          \
-{                                                                      \
-       unsigned long error_code;                                       \
-                                                                       \
-       /* Check if it's a DSP instruction */                           \
-       if (is_dsp_inst(&regs)) {                                       \
-               /* Enable DSP mode, and restart instruction. */         \
-               regs.sr |= SR_DSP;                                      \
-               return;                                                 \
-       }                                                               \
-                                                                       \
-       asm volatile("stc       r2_bank, %0": "=r" (error_code));       \
-       local_irq_enable();                                             \
-       tsk->thread.error_code = error_code;                            \
-       tsk->thread.trap_no = trapnr;                                   \
-        CHK_REMOTE_DEBUG(&regs);                                       \
-       force_sig(signr, tsk);                                          \
-       die_if_no_fixup(str,&regs,error_code);                          \
-}
-
 #ifdef CONFIG_CPU_SH2
 #define TRAP_RESERVED_INST     4
 #define TRAP_ILLEGAL_SLOT_INST 6
@@ -86,7 +61,7 @@ asmlinkage void do_##name(unsigned long r4, unsigned long r5,         \
 #define VMALLOC_OFFSET (8*1024*1024)
 #define MODULE_RANGE (8*1024*1024)
 
-spinlock_t die_lock;
+DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
@@ -575,8 +550,117 @@ int is_dsp_inst(struct pt_regs *regs)
 #define is_dsp_inst(regs)      (0)
 #endif /* CONFIG_SH_DSP */
 
-DO_ERROR(TRAP_RESERVED_INST, SIGILL, "reserved instruction", reserved_inst, current)
-DO_ERROR(TRAP_ILLEGAL_SLOT_INST, SIGILL, "illegal slot instruction", illegal_slot_inst, current)
+extern int do_fpu_inst(unsigned short, struct pt_regs*);
+
+asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs regs)
+{
+       unsigned long error_code;
+       struct task_struct *tsk = current;
+
+#ifdef CONFIG_SH_FPU_EMU
+       unsigned short inst;
+       int err;
+
+       get_user(inst, (unsigned short*)regs.pc);
+
+       err = do_fpu_inst(inst, &regs);
+       if (!err) {
+               regs.pc += 2;
+               return;
+       }
+       /* not a FPU inst. */
+#endif
+
+#ifdef CONFIG_SH_DSP
+       /* Check if it's a DSP instruction */
+       if (is_dsp_inst(&regs)) {
+               /* Enable DSP mode, and restart instruction. */
+               regs.sr |= SR_DSP;
+               return;
+       }
+#endif
+
+       asm volatile("stc       r2_bank, %0": "=r" (error_code));
+       local_irq_enable();
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = TRAP_RESERVED_INST;
+       CHK_REMOTE_DEBUG(&regs);
+       force_sig(SIGILL, tsk);
+       die_if_no_fixup("reserved instruction", &regs, error_code);
+}
+
+#ifdef CONFIG_SH_FPU_EMU
+static int emulate_branch(unsigned short inst, struct pt_regs* regs)
+{
+       /*
+        * bfs: 8fxx: PC+=d*2+4;
+        * bts: 8dxx: PC+=d*2+4;
+        * bra: axxx: PC+=D*2+4;
+        * bsr: bxxx: PC+=D*2+4  after PR=PC+4;
+        * braf:0x23: PC+=Rn*2+4;
+        * bsrf:0x03: PC+=Rn*2+4 after PR=PC+4;
+        * jmp: 4x2b: PC=Rn;
+        * jsr: 4x0b: PC=Rn      after PR=PC+4;
+        * rts: 000b: PC=PR;
+        */
+       if ((inst & 0xfd00) == 0x8d00) {
+               regs->pc += SH_PC_8BIT_OFFSET(inst);
+               return 0;
+       }
+
+       if ((inst & 0xe000) == 0xa000) {
+               regs->pc += SH_PC_12BIT_OFFSET(inst);
+               return 0;
+       }
+
+       if ((inst & 0xf0df) == 0x0003) {
+               regs->pc += regs->regs[(inst & 0x0f00) >> 8] + 4;
+               return 0;
+       }
+
+       if ((inst & 0xf0df) == 0x400b) {
+               regs->pc = regs->regs[(inst & 0x0f00) >> 8];
+               return 0;
+       }
+
+       if ((inst & 0xffff) == 0x000b) {
+               regs->pc = regs->pr;
+               return 0;
+       }
+
+       return 1;
+}
+#endif
+
+asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs regs)
+{
+       unsigned long error_code;
+       struct task_struct *tsk = current;
+#ifdef CONFIG_SH_FPU_EMU
+       unsigned short inst;
+
+       get_user(inst, (unsigned short *)regs.pc + 1);
+       if (!do_fpu_inst(inst, &regs)) {
+               get_user(inst, (unsigned short *)regs.pc);
+               if (!emulate_branch(inst, &regs))
+                       return;
+               /* fault in branch.*/
+       }
+       /* not a FPU inst. */
+#endif
+
+       asm volatile("stc       r2_bank, %0": "=r" (error_code));
+       local_irq_enable();
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = TRAP_RESERVED_INST;
+       CHK_REMOTE_DEBUG(&regs);
+       force_sig(SIGILL, tsk);
+       die_if_no_fixup("illegal slot instruction", &regs, error_code);
+}
 
 asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
                                   unsigned long r6, unsigned long r7,
@@ -634,14 +718,16 @@ void __init trap_init(void)
        exception_handling_table[TRAP_ILLEGAL_SLOT_INST]
                = (void *)do_illegal_slot_inst;
 
-#ifdef CONFIG_CPU_SH4
-       if (!(cpu_data->flags & CPU_HAS_FPU)) {
-               /* For SH-4 lacking an FPU, treat floating point instructions
-                  as reserved. */
-               /* entry 64 corresponds to EXPEVT=0x800 */
-               exception_handling_table[64] = (void *)do_reserved_inst;
-               exception_handling_table[65] = (void *)do_illegal_slot_inst;
-       }
+#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \
+    defined(CONFIG_SH_FPU_EMU)
+       /*
+        * For SH-4 lacking an FPU, treat floating point instructions as
+        * reserved. They'll be handled in the math-emu case, or faulted on
+        * otherwise.
+        */
+       /* entry 64 corresponds to EXPEVT=0x800 */
+       exception_handling_table[64] = (void *)do_reserved_inst;
+       exception_handling_table[65] = (void *)do_illegal_slot_inst;
 #endif
                
        /* Setup VBR for boot cpu */
@@ -655,20 +741,12 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
        unsigned long module_end = VMALLOC_END;
        int i = 1;
 
-       if (tsk && !sp) {
+       if (!tsk)
+               tsk = current;
+       if (tsk == current)
+               sp = (unsigned long *)current_stack_pointer;
+       else
                sp = (unsigned long *)tsk->thread.sp;
-       }
-
-       if (!sp) {
-               __asm__ __volatile__ (
-                       "mov r15, %0\n\t"
-                       "stc r7_bank, %1\n\t"
-                       : "=r" (module_start),
-                         "=r" (module_end)
-               );
-               
-               sp = (unsigned long *)module_start;
-       }
 
        stack = sp;
 
index 95fdd9135fcfa54f2f1cb8034ace006a78009036..5eb9309181865a15343d39934af2bf282ef57c94 100644 (file)
@@ -2,6 +2,7 @@
  * ld script to make SuperH Linux kernel
  * Written by Niibe Yutaka
  */
+#include <asm/thread_info.h>
 #include <asm-generic/vmlinux.lds.h>
 
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
@@ -13,7 +14,7 @@ OUTPUT_ARCH(sh)
 ENTRY(_start)
 SECTIONS
 {
-  . = 0x80000000 + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
+  . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET;
   _text = .;                   /* Text and read-only data */
   text = .;                    /* Text and read-only data */
   .empty_zero_page : {
@@ -40,16 +41,16 @@ SECTIONS
        *(.data)
 
         /* Align the initial ramdisk image (INITRD) on page boundaries. */
-        . = ALIGN(4096);
+        . = ALIGN(PAGE_SIZE);
         __rd_start = .;
         *(.initrd)
-        . = ALIGN(4096);
+        . = ALIGN(PAGE_SIZE);
         __rd_end = .;
 
        CONSTRUCTORS
        }
 
-  . = ALIGN(4096);
+  . = ALIGN(PAGE_SIZE);
   .data.page_aligned : { *(.data.idt) }
 
   . = ALIGN(32);
@@ -60,12 +61,10 @@ SECTIONS
 
   _edata = .;                  /* End of data section */
 
-  . = ALIGN(8192);             /* init_task */
+  . = ALIGN(THREAD_SIZE);              /* init_task */
   .data.init_task : { *(.data.init_task) }
-  /* stack */
-  .stack : { stack = .;  _stack = .; }
 
-  . = ALIGN(4096);             /* Init code and data */
+  . = ALIGN(PAGE_SIZE);                /* Init code and data */
   __init_begin = .;
   _sinittext = .;
   .init.text : { *(.init.text) }
@@ -96,7 +95,7 @@ SECTIONS
   __machvec_start = .;
   .init.machvec : { *(.init.machvec) }
   __machvec_end = .;
-  . = ALIGN(4096);
+  . = ALIGN(PAGE_SIZE);
   __init_end = .;
 
   . = ALIGN(4);
diff --git a/arch/sh/kernel/vsyscall/Makefile b/arch/sh/kernel/vsyscall/Makefile
new file mode 100644 (file)
index 0000000..4bbce1c
--- /dev/null
@@ -0,0 +1,36 @@
+obj-y += vsyscall.o vsyscall-syscall.o
+
+$(obj)/vsyscall-syscall.o: \
+       $(foreach F,trapa,$(obj)/vsyscall-$F.so)
+
+# Teach kbuild about targets
+targets += $(foreach F,trapa,vsyscall-$F.o vsyscall-$F.so)
+targets += vsyscall-note.o vsyscall.lds
+
+# The DSO images are built using a special linker script
+quiet_cmd_syscall = SYSCALL $@
+      cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \
+                          -Wl,-T,$(filter-out FORCE,$^) -o $@
+
+export CPPFLAGS_vsyscall.lds += -P -C -Ush
+
+vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 \
+               $(call ld-option, -Wl$(comma)--hash-style=sysv)
+
+SYSCFLAGS_vsyscall-trapa.so    = $(vsyscall-flags)
+
+$(obj)/vsyscall-trapa.so: \
+$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
+       $(call if_changed,syscall)
+
+# We also create a special relocatable object that should mirror the symbol
+# table and layout of the linked DSO.  With ld -R we can then refer to
+# these symbols in the kernel code rather than hand-coded addresses.
+extra-y += vsyscall-syms.o
+$(obj)/built-in.o: $(obj)/vsyscall-syms.o
+$(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o
+
+SYSCFLAGS_vsyscall-syms.o = -r
+$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
+                       $(obj)/vsyscall-trapa.o $(obj)/vsyscall-note.o FORCE
+       $(call if_changed,syscall)
diff --git a/arch/sh/kernel/vsyscall/vsyscall-note.S b/arch/sh/kernel/vsyscall/vsyscall-note.S
new file mode 100644 (file)
index 0000000..d4b5be4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ */
+
+#include <linux/uts.h>
+#include <linux/version.h>
+
+#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type)                        \
+       .section name, flags;                                                 \
+       .balign 4;                                                            \
+       .long 1f - 0f;          /* name length */                             \
+       .long 3f - 2f;          /* data length */                             \
+       .long type;             /* note type */                               \
+0:     .asciz vendor;          /* vendor name */                             \
+1:     .balign 4;                                                            \
+2:
+
+#define ASM_ELF_NOTE_END                                                     \
+3:     .balign 4;              /* pad out section */                         \
+       .previous
+
+       ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0)
+       .long LINUX_VERSION_CODE
+       ASM_ELF_NOTE_END
diff --git a/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S b/arch/sh/kernel/vsyscall/vsyscall-sigreturn.S
new file mode 100644 (file)
index 0000000..555a64f
--- /dev/null
@@ -0,0 +1,39 @@
+#include <asm/unistd.h>
+
+       .text
+       .balign 32
+       .globl __kernel_sigreturn
+       .type __kernel_sigreturn,@function
+__kernel_sigreturn:
+.LSTART_sigreturn:
+       mov.w   1f, r3
+       trapa   #0x10
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+
+1:     .short  __NR_sigreturn
+.LEND_sigreturn:
+       .size __kernel_sigreturn,.-.LSTART_sigreturn
+
+       .balign 32
+       .globl __kernel_rt_sigreturn
+       .type __kernel_rt_sigreturn,@function
+__kernel_rt_sigreturn:
+.LSTART_rt_sigreturn:
+       mov.w   1f, r3
+       trapa   #0x10
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+       or      r0, r0
+
+1:     .short  __NR_rt_sigreturn
+.LEND_rt_sigreturn:
+       .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn
+
+       .section .eh_frame,"a",@progbits
+       .previous
diff --git a/arch/sh/kernel/vsyscall/vsyscall-syscall.S b/arch/sh/kernel/vsyscall/vsyscall-syscall.S
new file mode 100644 (file)
index 0000000..c2ac7f0
--- /dev/null
@@ -0,0 +1,10 @@
+#include <linux/init.h>
+
+__INITDATA
+
+       .globl vsyscall_trapa_start, vsyscall_trapa_end
+vsyscall_trapa_start:
+       .incbin "arch/sh/kernel/vsyscall/vsyscall-trapa.so"
+vsyscall_trapa_end:
+
+__FINIT
diff --git a/arch/sh/kernel/vsyscall/vsyscall-trapa.S b/arch/sh/kernel/vsyscall/vsyscall-trapa.S
new file mode 100644 (file)
index 0000000..3b6eb34
--- /dev/null
@@ -0,0 +1,42 @@
+       .text
+       .globl __kernel_vsyscall
+       .type __kernel_vsyscall,@function
+__kernel_vsyscall:
+.LSTART_vsyscall:
+       /* XXX: We'll have to do something here once we opt to use the vDSO
+        * page for something other than the signal trampoline.. as well as
+        * fill out .eh_frame -- PFM. */
+.LEND_vsyscall:
+       .size __kernel_vsyscall,.-.LSTART_vsyscall
+       .previous
+
+       .section .eh_frame,"a",@progbits
+.LCIE:
+       .ualong .LCIE_end - .LCIE_start
+.LCIE_start:
+       .ualong 0               /* CIE ID */
+       .byte   0x1             /* Version number */
+       .string "zRS"           /* NUL-terminated augmentation string */
+       .uleb128 0x1            /* Code alignment factor */
+       .sleb128 -4             /* Data alignment factor */
+       .byte   0x11            /* Return address register column */
+                               /* Augmentation length and data (none) */
+       .byte   0xc             /* DW_CFA_def_cfa */
+       .uleb128 0xf            /* r15 */
+       .uleb128 0x0            /* offset 0 */
+
+       .align 2
+.LCIE_end:
+
+       .ualong .LFDE_end-.LFDE_start   /* Length FDE */
+.LFDE_start:
+       .ualong .LCIE                   /* CIE pointer */
+       .ualong .LSTART_vsyscall-.      /* start address */
+       .ualong .LEND_vsyscall-.LSTART_vsyscall
+       .uleb128 0
+       .align 2
+.LFDE_end:
+       .previous
+
+/* Get the common code for the sigreturn entry points */
+#include "vsyscall-sigreturn.S"
diff --git a/arch/sh/kernel/vsyscall/vsyscall.c b/arch/sh/kernel/vsyscall/vsyscall.c
new file mode 100644 (file)
index 0000000..075d6cc
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * arch/sh/kernel/vsyscall.c
+ *
+ *  Copyright (C) 2006 Paul Mundt
+ *
+ * vDSO randomization
+ * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar
+ *
+ * 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/slab.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <linux/elf.h>
+
+/*
+ * Should the kernel map a VDSO page into processes and pass its
+ * address down to glibc upon exec()?
+ */
+unsigned int __read_mostly vdso_enabled = 1;
+EXPORT_SYMBOL_GPL(vdso_enabled);
+
+static int __init vdso_setup(char *s)
+{
+       vdso_enabled = simple_strtoul(s, NULL, 0);
+       return 1;
+}
+__setup("vdso=", vdso_setup);
+
+/*
+ * These symbols are defined by vsyscall.o to mark the bounds
+ * of the ELF DSO images included therein.
+ */
+extern const char vsyscall_trapa_start, vsyscall_trapa_end;
+static void *syscall_page;
+
+int __init vsyscall_init(void)
+{
+       syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
+
+       /*
+        * XXX: Map this page to a fixmap entry if we get around
+        * to adding the page to ELF core dumps
+        */
+
+       memcpy(syscall_page,
+              &vsyscall_trapa_start,
+              &vsyscall_trapa_end - &vsyscall_trapa_start);
+
+       return 0;
+}
+
+static struct page *syscall_vma_nopage(struct vm_area_struct *vma,
+                                      unsigned long address, int *type)
+{
+       unsigned long offset = address - vma->vm_start;
+       struct page *page;
+
+       if (address < vma->vm_start || address > vma->vm_end)
+               return NOPAGE_SIGBUS;
+
+       page = virt_to_page(syscall_page + offset);
+
+       get_page(page);
+
+       return page;
+}
+
+/* Prevent VMA merging */
+static void syscall_vma_close(struct vm_area_struct *vma)
+{
+}
+
+static struct vm_operations_struct syscall_vm_ops = {
+       .nopage = syscall_vma_nopage,
+       .close  = syscall_vma_close,
+};
+
+/* Setup a VMA at program startup for the vsyscall page */
+int arch_setup_additional_pages(struct linux_binprm *bprm,
+                               int executable_stack)
+{
+       struct vm_area_struct *vma;
+       struct mm_struct *mm = current->mm;
+       unsigned long addr;
+       int ret;
+
+       down_write(&mm->mmap_sem);
+       addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
+       if (IS_ERR_VALUE(addr)) {
+               ret = addr;
+               goto up_fail;
+       }
+
+       vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
+       if (!vma) {
+               ret = -ENOMEM;
+               goto up_fail;
+       }
+
+       vma->vm_start = addr;
+       vma->vm_end = addr + PAGE_SIZE;
+       /* MAYWRITE to allow gdb to COW and set breakpoints */
+       vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYEXEC|VM_MAYWRITE;
+       vma->vm_flags |= mm->def_flags;
+       vma->vm_page_prot = protection_map[vma->vm_flags & 7];
+       vma->vm_ops = &syscall_vm_ops;
+       vma->vm_mm = mm;
+
+       ret = insert_vm_struct(mm, vma);
+       if (unlikely(ret)) {
+               kmem_cache_free(vm_area_cachep, vma);
+               goto up_fail;
+       }
+
+       current->mm->context.vdso = (void *)addr;
+
+       mm->total_vm++;
+up_fail:
+       up_write(&mm->mmap_sem);
+       return ret;
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+       if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
+               return "[vdso]";
+
+       return NULL;
+}
+
+struct vm_area_struct *get_gate_vma(struct task_struct *task)
+{
+       return NULL;
+}
+
+int in_gate_area(struct task_struct *task, unsigned long address)
+{
+       return 0;
+}
+
+int in_gate_area_no_task(unsigned long address)
+{
+       return 0;
+}
diff --git a/arch/sh/kernel/vsyscall/vsyscall.lds.S b/arch/sh/kernel/vsyscall/vsyscall.lds.S
new file mode 100644 (file)
index 0000000..b13c3d4
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Linker script for vsyscall DSO.  The vsyscall page is an ELF shared
+ * object prelinked to its virtual address, and with only one read-only
+ * segment (that fits in one page).  This script controls its layout.
+ */
+#include <asm/asm-offsets.h>
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+OUTPUT_FORMAT("elf32-sh-linux", "elf32-sh-linux", "elf32-sh-linux")
+#else
+OUTPUT_FORMAT("elf32-shbig-linux", "elf32-shbig-linux", "elf32-shbig-linux")
+#endif
+OUTPUT_ARCH(sh)
+
+/* The ELF entry point can be used to set the AT_SYSINFO value.  */
+ENTRY(__kernel_vsyscall);
+
+SECTIONS
+{
+  . = SIZEOF_HEADERS;
+
+  .hash           : { *(.hash) }               :text
+  .gnu.hash       : { *(.gnu.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+
+  /* This linker script is used both with -r and with -shared.
+     For the layouts to match, we need to skip more than enough
+     space for the dynamic symbol table et al.  If this amount
+     is insufficient, ld -shared will barf.  Just increase it here.  */
+  . = 0x400;
+
+  .text           : { *(.text) }               :text =0x90909090
+  .note                  : { *(.note.*) }              :text :note
+  .eh_frame_hdr   : { *(.eh_frame_hdr) }       :text :eh_frame_hdr
+  .eh_frame       : { KEEP (*(.eh_frame)) }    :text
+  .dynamic        : { *(.dynamic) }            :text :dynamic
+  .useless        : {
+       *(.got.plt) *(.got)
+       *(.data .data.* .gnu.linkonce.d.*)
+       *(.dynbss)
+       *(.bss .bss.* .gnu.linkonce.b.*)
+  }                                            :text
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+  text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+  dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+  note PT_NOTE FLAGS(4); /* PF_R */
+  eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+  LINUX_2.6 {
+    global:
+       __kernel_vsyscall;
+       __kernel_sigreturn;
+       __kernel_rt_sigreturn;
+
+    local: *;
+  };
+}
index 7c50dfe68c07707cab8b8e8793a98a423741b68e..cbdd0d40e545f0fa0d5cea817a472f46175f5a47 100644 (file)
@@ -202,8 +202,9 @@ ENTRY(csum_partial_copy_generic)
        cmp/pz  r6              ! Jump if we had at least two bytes.
        bt/s    1f
         clrt
+       add     #2,r6           ! r6 was < 2.   Deal with it.
        bra     4f
-        add    #2,r6           ! r6 was < 2.   Deal with it.
+        mov    r6,r2
 
 3:     ! Handle different src and dest alignments.
        ! This is not common, so simple byte by byte copy will do.
index db6b736537adf9ff7e46f7aa7d69bd8260a83a19..560bc17eebdd6748d1e49e40730a476b3cbe1c3a 100644 (file)
@@ -727,8 +727,8 @@ ENTRY(memcpy)
        mov.l   @(0x04,r5), r11 !  18 LS (latency=2)
        xtrct   r9, r8          !  48 EX
 
-       mov.w   @(0x02,r5), r12 !  18 LS (latency=2)
-       xtrct   r10, r9         !  48 EX
+       mov.l   @(0x00,r5), r12 !  18 LS (latency=2)
+       xtrct   r10, r9         !  48 EX
 
        movca.l r0,@r1          !  40 LS (latency=3-7)
        add     #-0x1c, r1      !  50 EX
index 95670090680e5d5c6e6396c1a730a1ade66edd97..af91fe2b72a66e571ed3c7f08fca44b68f4a4565 100644 (file)
@@ -29,6 +29,7 @@ ENTRY(memset)
        bf/s    1b
         mov.b  r5,@-r4
 2:                             ! make VVVV
+       extu.b  r5,r5
        swap.b  r5,r0           !   V0
        or      r0,r5           !   VV
        swap.w  r5,r0           ! VV00
diff --git a/arch/sh/math-emu/Makefile b/arch/sh/math-emu/Makefile
new file mode 100644 (file)
index 0000000..638b342
--- /dev/null
@@ -0,0 +1 @@
+obj-y  := math.o
diff --git a/arch/sh/math-emu/math.c b/arch/sh/math-emu/math.c
new file mode 100644 (file)
index 0000000..26b6046
--- /dev/null
@@ -0,0 +1,624 @@
+/*
+ * arch/sh/math-emu/math.c
+ *
+ * Copyright (C) 2006 Takashi YOSHII <takasi-y@ops.dti.ne.jp>
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+#include "sfp-util.h"
+#include <math-emu/soft-fp.h>
+#include <math-emu/single.h>
+#include <math-emu/double.h>
+
+#define        FPUL            (fregs->fpul)
+#define FPSCR          (fregs->fpscr)
+#define FPSCR_RM       (FPSCR&3)
+#define FPSCR_DN       ((FPSCR>>18)&1)
+#define FPSCR_PR       ((FPSCR>>19)&1)
+#define FPSCR_SZ       ((FPSCR>>20)&1)
+#define FPSCR_FR       ((FPSCR>>21)&1)
+#define FPSCR_MASK     0x003fffffUL
+
+#define BANK(n)        (n^(FPSCR_FR?16:0))
+#define FR     ((unsigned long*)(fregs->fp_regs))
+#define FR0    (FR[BANK(0)])
+#define FRn    (FR[BANK(n)])
+#define FRm    (FR[BANK(m)])
+#define DR     ((unsigned long long*)(fregs->fp_regs))
+#define DRn    (DR[BANK(n)/2])
+#define DRm    (DR[BANK(m)/2])
+
+#define XREG(n)        (n^16)
+#define XFn    (FR[BANK(XREG(n))])
+#define XFm    (FR[BANK(XREG(m))])
+#define XDn    (DR[BANK(XREG(n))/2])
+#define XDm    (DR[BANK(XREG(m))/2])
+
+#define R0     (regs->regs[0])
+#define Rn     (regs->regs[n])
+#define Rm     (regs->regs[m])
+
+#define WRITE(d,a)     ({if(put_user(d, (typeof (d)*)a)) return -EFAULT;})
+#define READ(d,a)      ({if(get_user(d, (typeof (d)*)a)) return -EFAULT;})
+
+#define PACK_S(r,f)    FP_PACK_SP(&r,f)
+#define UNPACK_S(f,r)  FP_UNPACK_SP(f,&r)
+#define PACK_D(r,f) \
+       {u32 t[2]; FP_PACK_DP(t,f); ((u32*)&r)[0]=t[1]; ((u32*)&r)[1]=t[0];}
+#define UNPACK_D(f,r) \
+       {u32 t[2]; t[0]=((u32*)&r)[1]; t[1]=((u32*)&r)[0]; FP_UNPACK_DP(f,t);}
+
+// 2 args instructions.
+#define BOTH_PRmn(op,x) \
+       FP_DECL_EX; if(FPSCR_PR) op(D,x,DRm,DRn); else op(S,x,FRm,FRn);
+
+#define CMP_X(SZ,R,M,N) do{ \
+       FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); \
+       UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
+       FP_CMP_##SZ(R, Fn, Fm, 2); }while(0)
+#define EQ_X(SZ,R,M,N) do{ \
+       FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); \
+       UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
+       FP_CMP_EQ_##SZ(R, Fn, Fm); }while(0)
+#define CMP(OP) ({ int r; BOTH_PRmn(OP##_X,r); r; })
+
+static int
+fcmp_gt(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       if (CMP(CMP) > 0)
+               regs->sr |= 1;
+       else
+               regs->sr &= ~1;
+
+       return 0;
+}
+
+static int
+fcmp_eq(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       if (CMP(CMP /*EQ*/) == 0)
+               regs->sr |= 1;
+       else
+               regs->sr &= ~1;
+       return 0;
+}
+
+#define ARITH_X(SZ,OP,M,N) do{ \
+       FP_DECL_##SZ(Fm); FP_DECL_##SZ(Fn); FP_DECL_##SZ(Fr); \
+       UNPACK_##SZ(Fm, M); UNPACK_##SZ(Fn, N); \
+       FP_##OP##_##SZ(Fr, Fn, Fm); \
+       PACK_##SZ(N, Fr); }while(0)
+
+static int
+fadd(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       BOTH_PRmn(ARITH_X, ADD);
+       return 0;
+}
+
+static int
+fsub(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       BOTH_PRmn(ARITH_X, SUB);
+       return 0;
+}
+
+static int
+fmul(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       BOTH_PRmn(ARITH_X, MUL);
+       return 0;
+}
+
+static int
+fdiv(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       BOTH_PRmn(ARITH_X, DIV);
+       return 0;
+}
+
+static int
+fmac(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       FP_DECL_EX;
+       FP_DECL_S(Fr);
+       FP_DECL_S(Ft);
+       FP_DECL_S(F0);
+       FP_DECL_S(Fm);
+       FP_DECL_S(Fn);
+       UNPACK_S(F0, FR0);
+       UNPACK_S(Fm, FRm);
+       UNPACK_S(Fn, FRn);
+       FP_MUL_S(Ft, Fm, F0);
+       FP_ADD_S(Fr, Fn, Ft);
+       PACK_S(FRn, Fr);
+       return 0;
+}
+
+// to process fmov's extention (odd n for DR access XD).
+#define FMOV_EXT(x) if(x&1) x+=16-1
+
+static int
+fmov_idx_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(n);
+               READ(FRn, Rm + R0 + 4);
+               n++;
+               READ(FRn, Rm + R0);
+       } else {
+               READ(FRn, Rm + R0);
+       }
+
+       return 0;
+}
+
+static int
+fmov_mem_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(n);
+               READ(FRn, Rm + 4);
+               n++;
+               READ(FRn, Rm);
+       } else {
+               READ(FRn, Rm);
+       }
+
+       return 0;
+}
+
+static int
+fmov_inc_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(n);
+               READ(FRn, Rm + 4);
+               n++;
+               READ(FRn, Rm);
+               Rm += 8;
+       } else {
+               READ(FRn, Rm);
+               Rm += 4;
+       }
+
+       return 0;
+}
+
+static int
+fmov_reg_idx(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(m);
+               WRITE(FRm, Rn + R0 + 4);
+               m++;
+               WRITE(FRm, Rn + R0);
+       } else {
+               WRITE(FRm, Rn + R0);
+       }
+
+       return 0;
+}
+
+static int
+fmov_reg_mem(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(m);
+               WRITE(FRm, Rn + 4);
+               m++;
+               WRITE(FRm, Rn);
+       } else {
+               WRITE(FRm, Rn);
+       }
+
+       return 0;
+}
+
+static int
+fmov_reg_dec(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(m);
+               Rn -= 8;
+               WRITE(FRm, Rn + 4);
+               m++;
+               WRITE(FRm, Rn);
+       } else {
+               Rn -= 4;
+               WRITE(FRm, Rn);
+       }
+
+       return 0;
+}
+
+static int
+fmov_reg_reg(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m,
+            int n)
+{
+       if (FPSCR_SZ) {
+               FMOV_EXT(m);
+               FMOV_EXT(n);
+               DRn = DRm;
+       } else {
+               FRn = FRm;
+       }
+
+       return 0;
+}
+
+static int
+fnop_mn(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int m, int n)
+{
+       return -EINVAL;
+}
+
+// 1 arg instructions.
+#define NOTYETn(i) static int i(struct sh_fpu_soft_struct *fregs, int n) \
+       { printk( #i " not yet done.\n"); return 0; }
+
+NOTYETn(ftrv)
+NOTYETn(fsqrt)
+NOTYETn(fipr)
+NOTYETn(fsca)
+NOTYETn(fsrra)
+
+#define EMU_FLOAT_X(SZ,N) do { \
+       FP_DECL_##SZ(Fn); \
+       FP_FROM_INT_##SZ(Fn, FPUL, 32, int); \
+       PACK_##SZ(N, Fn); }while(0)
+static int ffloat(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FP_DECL_EX;
+
+       if (FPSCR_PR)
+               EMU_FLOAT_X(D, DRn);
+       else
+               EMU_FLOAT_X(S, FRn);
+
+       return 0;
+}
+
+#define EMU_FTRC_X(SZ,N) do { \
+       FP_DECL_##SZ(Fn); \
+       UNPACK_##SZ(Fn, N); \
+       FP_TO_INT_##SZ(FPUL, Fn, 32, 1); }while(0)
+static int ftrc(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FP_DECL_EX;
+
+       if (FPSCR_PR)
+               EMU_FTRC_X(D, DRn);
+       else
+               EMU_FTRC_X(S, FRn);
+
+       return 0;
+}
+
+static int fcnvsd(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FP_DECL_EX;
+       FP_DECL_S(Fn);
+       FP_DECL_D(Fr);
+       UNPACK_S(Fn, FPUL);
+       FP_CONV(D, S, 2, 1, Fr, Fn);
+       PACK_D(DRn, Fr);
+       return 0;
+}
+
+static int fcnvds(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FP_DECL_EX;
+       FP_DECL_D(Fn);
+       FP_DECL_S(Fr);
+       UNPACK_D(Fn, DRn);
+       FP_CONV(S, D, 1, 2, Fr, Fn);
+       PACK_S(FPUL, Fr);
+       return 0;
+}
+
+static int fxchg(struct sh_fpu_soft_struct *fregs, int flag)
+{
+       FPSCR ^= flag;
+       return 0;
+}
+
+static int fsts(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FRn = FPUL;
+       return 0;
+}
+
+static int flds(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FPUL = FRn;
+       return 0;
+}
+
+static int fneg(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FRn ^= (1 << (_FP_W_TYPE_SIZE - 1));
+       return 0;
+}
+
+static int fabs(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FRn &= ~(1 << (_FP_W_TYPE_SIZE - 1));
+       return 0;
+}
+
+static int fld0(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FRn = 0;
+       return 0;
+}
+
+static int fld1(struct sh_fpu_soft_struct *fregs, int n)
+{
+       FRn = (_FP_EXPBIAS_S << (_FP_FRACBITS_S - 1));
+       return 0;
+}
+
+static int fnop_n(struct sh_fpu_soft_struct *fregs, int n)
+{
+       return -EINVAL;
+}
+
+/// Instruction decoders.
+
+static int id_fxfd(struct sh_fpu_soft_struct *, int);
+static int id_fnxd(struct sh_fpu_soft_struct *, struct pt_regs *, int, int);
+
+static int (*fnxd[])(struct sh_fpu_soft_struct *, int) = {
+       fsts, flds, ffloat, ftrc, fneg, fabs, fsqrt, fsrra,
+       fld0, fld1, fcnvsd, fcnvds, fnop_n, fnop_n, fipr, id_fxfd
+};
+
+static int (*fnmx[])(struct sh_fpu_soft_struct *, struct pt_regs *, int, int) = {
+       fadd, fsub, fmul, fdiv, fcmp_eq, fcmp_gt, fmov_idx_reg, fmov_reg_idx,
+       fmov_mem_reg, fmov_inc_reg, fmov_reg_mem, fmov_reg_dec,
+       fmov_reg_reg, id_fnxd, fmac, fnop_mn};
+
+static int id_fxfd(struct sh_fpu_soft_struct *fregs, int x)
+{
+       const int flag[] = { FPSCR_SZ, FPSCR_PR, FPSCR_FR, 0 };
+       switch (x & 3) {
+       case 3:
+               fxchg(fregs, flag[x >> 2]);
+               break;
+       case 1:
+               ftrv(fregs, x - 1);
+               break;
+       default:
+               fsca(fregs, x);
+       }
+       return 0;
+}
+
+static int
+id_fnxd(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, int x, int n)
+{
+       return (fnxd[x])(fregs, n);
+}
+
+static int
+id_fnmx(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, u16 code)
+{
+       int n = (code >> 8) & 0xf, m = (code >> 4) & 0xf, x = code & 0xf;
+       return (fnmx[x])(fregs, regs, m, n);
+}
+
+static int
+id_sys(struct sh_fpu_soft_struct *fregs, struct pt_regs *regs, u16 code)
+{
+       int n = ((code >> 8) & 0xf);
+       unsigned long *reg = (code & 0x0010) ? &FPUL : &FPSCR;
+
+       switch (code & 0xf0ff) {
+       case 0x005a:
+       case 0x006a:
+               Rn = *reg;
+               break;
+       case 0x405a:
+       case 0x406a:
+               *reg = Rn;
+               break;
+       case 0x4052:
+       case 0x4062:
+               Rn -= 4;
+               WRITE(*reg, Rn);
+               break;
+       case 0x4056:
+       case 0x4066:
+               READ(*reg, Rn);
+               Rn += 4;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int fpu_emulate(u16 code, struct sh_fpu_soft_struct *fregs, struct pt_regs *regs)
+{
+       if ((code & 0xf000) == 0xf000)
+               return id_fnmx(fregs, regs, code);
+       else
+               return id_sys(fregs, regs, code);
+}
+
+/**
+ *     denormal_to_double - Given denormalized float number,
+ *                          store double float
+ *
+ *     @fpu: Pointer to sh_fpu_hard structure
+ *     @n: Index to FP register
+ */
+static void denormal_to_double(struct sh_fpu_hard_struct *fpu, int n)
+{
+       unsigned long du, dl;
+       unsigned long x = fpu->fpul;
+       int exp = 1023 - 126;
+
+       if (x != 0 && (x & 0x7f800000) == 0) {
+               du = (x & 0x80000000);
+               while ((x & 0x00800000) == 0) {
+                       x <<= 1;
+                       exp--;
+               }
+               x &= 0x007fffff;
+               du |= (exp << 20) | (x >> 3);
+               dl = x << 29;
+
+               fpu->fp_regs[n] = du;
+               fpu->fp_regs[n+1] = dl;
+       }
+}
+
+/**
+ *     ieee_fpe_handler - Handle denormalized number exception
+ *
+ *     @regs: Pointer to register structure
+ *
+ *     Returns 1 when it's handled (should not cause exception).
+ */
+static int ieee_fpe_handler(struct pt_regs *regs)
+{
+       unsigned short insn = *(unsigned short *)regs->pc;
+       unsigned short finsn;
+       unsigned long nextpc;
+       int nib[4] = {
+               (insn >> 12) & 0xf,
+               (insn >> 8) & 0xf,
+               (insn >> 4) & 0xf,
+               insn & 0xf};
+
+       if (nib[0] == 0xb ||
+           (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */
+               regs->pr = regs->pc + 4;
+
+       if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */
+               nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3);
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */
+               if (regs->sr & 1)
+                       nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+               else
+                       nextpc = regs->pc + 4;
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */
+               if (regs->sr & 1)
+                       nextpc = regs->pc + 4;
+               else
+                       nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1);
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else if (nib[0] == 0x4 && nib[3] == 0xb &&
+                (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */
+               nextpc = regs->regs[nib[1]];
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else if (nib[0] == 0x0 && nib[3] == 0x3 &&
+                (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */
+               nextpc = regs->pc + 4 + regs->regs[nib[1]];
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else if (insn == 0x000b) { /* rts */
+               nextpc = regs->pr;
+               finsn = *(unsigned short *) (regs->pc + 2);
+       } else {
+               nextpc = regs->pc + 2;
+               finsn = insn;
+       }
+
+       if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */
+               struct task_struct *tsk = current;
+
+               if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) {
+                       /* FPU error */
+                       denormal_to_double (&tsk->thread.fpu.hard,
+                                           (finsn >> 8) & 0xf);
+                       tsk->thread.fpu.hard.fpscr &=
+                               ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
+                       set_tsk_thread_flag(tsk, TIF_USEDFPU);
+               } else {
+                       tsk->thread.trap_no = 11;
+                       tsk->thread.error_code = 0;
+                       force_sig(SIGFPE, tsk);
+               }
+
+               regs->pc = nextpc;
+               return 1;
+       }
+
+       return 0;
+}
+
+asmlinkage void do_fpu_error(unsigned long r4, unsigned long r5,
+                            unsigned long r6, unsigned long r7,
+                            struct pt_regs regs)
+{
+       struct task_struct *tsk = current;
+
+       if (ieee_fpe_handler (&regs))
+               return;
+
+       regs.pc += 2;
+       tsk->thread.trap_no = 11;
+       tsk->thread.error_code = 0;
+       force_sig(SIGFPE, tsk);
+}
+
+/**
+ * fpu_init - Initialize FPU registers
+ * @fpu: Pointer to software emulated FPU registers.
+ */
+static void fpu_init(struct sh_fpu_soft_struct *fpu)
+{
+       int i;
+
+       fpu->fpscr = FPSCR_INIT;
+       fpu->fpul = 0;
+
+       for (i = 0; i < 16; i++) {
+               fpu->fp_regs[i] = 0;
+               fpu->xfp_regs[i]= 0;
+       }
+}
+
+/**
+ * do_fpu_inst - Handle reserved instructions for FPU emulation
+ * @inst: instruction code.
+ * @regs: registers on stack.
+ */
+int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
+{
+       struct task_struct *tsk = current;
+       struct sh_fpu_soft_struct *fpu = &(tsk->thread.fpu.soft);
+
+       if (!test_tsk_thread_flag(tsk, TIF_USEDFPU)) {
+               /* initialize once. */
+               fpu_init(fpu);
+               set_tsk_thread_flag(tsk, TIF_USEDFPU);
+       }
+
+       return fpu_emulate(inst, fpu, regs);
+}
diff --git a/arch/sh/math-emu/sfp-util.h b/arch/sh/math-emu/sfp-util.h
new file mode 100644 (file)
index 0000000..8ae1bd3
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * These are copied from glibc/stdlib/longlong.h
+ */
+
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+  do {                                                                  \
+    UWtype __x;                                                         \
+    __x = (al) + (bl);                                                  \
+    (sh) = (ah) + (bh) + (__x < (al));                                  \
+    (sl) = __x;                                                         \
+  } while (0)
+
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+  do {                                                                  \
+    UWtype __x;                                                         \
+    __x = (al) - (bl);                                                  \
+    (sh) = (ah) - (bh) - (__x > (al));                                  \
+    (sl) = __x;                                                         \
+  } while (0)
+
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("dmulu.l %2,%3\n\tsts    macl,%1\n\tsts  mach,%0"   \
+       : "=r" ((u32)(w1)), "=r" ((u32)(w0))    \
+       :  "r" ((u32)(u)),   "r" ((u32)(v))     \
+       : "macl", "mach")
+
+#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
+#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
+
+#define udiv_qrnnd(q, r, n1, n0, d) \
+  do {                                                                 \
+    UWtype __d1, __d0, __q1, __q0;                                     \
+    UWtype __r1, __r0, __m;                                            \
+    __d1 = __ll_highpart (d);                                          \
+    __d0 = __ll_lowpart (d);                                           \
+                                                                       \
+    __r1 = (n1) % __d1;                                                        \
+    __q1 = (n1) / __d1;                                                        \
+    __m = (UWtype) __q1 * __d0;                                                \
+    __r1 = __r1 * __ll_B | __ll_highpart (n0);                         \
+    if (__r1 < __m)                                                    \
+      {                                                                        \
+       __q1--, __r1 += (d);                                            \
+       if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
+         if (__r1 < __m)                                               \
+           __q1--, __r1 += (d);                                        \
+      }                                                                        \
+    __r1 -= __m;                                                       \
+                                                                       \
+    __r0 = __r1 % __d1;                                                        \
+    __q0 = __r1 / __d1;                                                        \
+    __m = (UWtype) __q0 * __d0;                                                \
+    __r0 = __r0 * __ll_B | __ll_lowpart (n0);                          \
+    if (__r0 < __m)                                                    \
+      {                                                                        \
+       __q0--, __r0 += (d);                                            \
+       if (__r0 >= (d))                                                \
+         if (__r0 < __m)                                               \
+           __q0--, __r0 += (d);                                        \
+      }                                                                        \
+    __r0 -= __m;                                                       \
+                                                                       \
+    (q) = (UWtype) __q1 * __ll_B | __q0;                               \
+    (r) = __r0;                                                                \
+  } while (0)
+
+#define abort()        return 0
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+
index fb586b1cf8bb6b236d9b458110ef5a2740af3fb8..9dd606464d234347d4e0f94bec69b34f129e2a42 100644 (file)
@@ -20,7 +20,10 @@ config CPU_SH4
 config CPU_SH4A
        bool
        select CPU_SH4
-       select CPU_HAS_INTC2_IRQ
+
+config CPU_SH4AL_DSP
+       bool
+       select CPU_SH4A
 
 config CPU_SUBTYPE_ST40
        bool
@@ -48,6 +51,12 @@ config CPU_SUBTYPE_SH7705
        select CPU_SH3
        select CPU_HAS_PINT_IRQ
 
+config CPU_SUBTYPE_SH7706
+       bool "Support SH7706 processor"
+       select CPU_SH3
+       help
+         Select SH7706 if you have a 133 Mhz SH-3 HD6417706 CPU.
+
 config CPU_SUBTYPE_SH7707
        bool "Support SH7707 processor"
        select CPU_SH3
@@ -69,6 +78,12 @@ config CPU_SUBTYPE_SH7709
        help
          Select SH7709 if you have a  80 Mhz SH-3 HD6417709 CPU.
 
+config CPU_SUBTYPE_SH7710
+       bool "Support SH7710 processor"
+       select CPU_SH3
+       help
+         Select SH7710 if you have a SH3-DSP SH7710 CPU.
+
 comment "SH-4 Processor Support"
 
 config CPU_SUBTYPE_SH7750
@@ -133,10 +148,6 @@ config CPU_SUBTYPE_ST40GX1
 
 comment "SH-4A Processor Support"
 
-config CPU_SUBTYPE_SH73180
-       bool "Support SH73180 processor"
-       select CPU_SH4A
-
 config CPU_SUBTYPE_SH7770
        bool "Support SH7770 processor"
        select CPU_SH4A
@@ -144,6 +155,17 @@ config CPU_SUBTYPE_SH7770
 config CPU_SUBTYPE_SH7780
        bool "Support SH7780 processor"
        select CPU_SH4A
+       select CPU_HAS_INTC2_IRQ
+
+comment "SH4AL-DSP Processor Support"
+
+config CPU_SUBTYPE_SH73180
+       bool "Support SH73180 processor"
+       select CPU_SH4AL_DSP
+
+config CPU_SUBTYPE_SH7343
+       bool "Support SH7343 processor"
+       select CPU_SH4AL_DSP
 
 endmenu
 
@@ -161,15 +183,59 @@ config MMU
          turning this off will boot the kernel on these machines with the
          MMU implicitly switched off.
 
+config PAGE_OFFSET
+       hex
+       default "0x80000000" if MMU
+       default "0x00000000"
+
+config MEMORY_START
+       hex "Physical memory start address"
+       default "0x08000000"
+       ---help---
+         Computers built with Hitachi SuperH processors always
+         map the ROM starting at address zero.  But the processor
+         does not specify the range that RAM takes.
+
+         The physical memory (RAM) start address will be automatically
+         set to 08000000. Other platforms, such as the Solution Engine
+         boards typically map RAM at 0C000000.
+
+         Tweak this only when porting to a new machine which does not
+         already have a defconfig. Changing it from the known correct
+         value on any of the known systems will only lead to disaster.
+
+config MEMORY_SIZE
+       hex "Physical memory size"
+       default "0x00400000"
+       help
+         This sets the default memory size assumed by your SH kernel. It can
+         be overridden as normal by the 'mem=' argument on the kernel command
+         line. If unsure, consult your board specifications or just leave it
+         as 0x00400000 which was the default value before this became
+         configurable.
+
 config 32BIT
        bool "Support 32-bit physical addressing through PMB"
-       depends on CPU_SH4A
+       depends on CPU_SH4A && MMU
        default y
        help
          If you say Y here, physical addressing will be extended to
          32-bits through the SH-4A PMB. If this is not set, legacy
          29-bit physical addressing will be used.
 
+config VSYSCALL
+       bool "Support vsyscall page"
+       depends on MMU
+       default y
+       help
+         This will enable support for the kernel mapping a vDSO page
+         in process space, and subsequently handing down the entry point
+         to the libc through the ELF auxiliary vector.
+
+         From the kernel side this is used for the signal trampoline.
+         For systems with an MMU that can afford to give up a page,
+         (the default value) say Y.
+
 choice
        prompt "HugeTLB page size"
        depends on HUGETLB_PAGE && CPU_SH4 && MMU
index 9489a1424644e7368a4ee9d956703987c14ca72d..3ffd7f68c0a206befbcc7ca3f1a940a73027dfb2 100644 (file)
@@ -6,20 +6,26 @@ obj-y                 := init.o extable.o consistent.o
 
 obj-$(CONFIG_CPU_SH2)  += cache-sh2.o
 obj-$(CONFIG_CPU_SH3)  += cache-sh3.o
-obj-$(CONFIG_CPU_SH4)  += cache-sh4.o pg-sh4.o
+obj-$(CONFIG_CPU_SH4)  += cache-sh4.o
 
 obj-$(CONFIG_DMA_PAGE_OPS)     += pg-dma.o
 obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
 
 mmu-y                  := fault-nommu.o tlb-nommu.o pg-nommu.o
-mmu-$(CONFIG_MMU)      := fault.o clear_page.o copy_page.o
+mmu-$(CONFIG_MMU)      := fault.o clear_page.o copy_page.o tlb-flush.o \
+                          ioremap.o
 
 obj-y                  += $(mmu-y)
 
+ifdef CONFIG_DEBUG_FS
+obj-$(CONFIG_CPU_SH4)          += cache-debugfs.o
+endif
+
 ifdef CONFIG_MMU
-obj-$(CONFIG_CPU_SH3)  += tlb-sh3.o
-obj-$(CONFIG_CPU_SH4)  += tlb-sh4.o ioremap.o
+obj-$(CONFIG_CPU_SH3)          += tlb-sh3.o
+obj-$(CONFIG_CPU_SH4)          += tlb-sh4.o pg-sh4.o
 obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o
 endif
 
-obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
+obj-$(CONFIG_SH7705_CACHE_32KB)        += cache-sh7705.o
+obj-$(CONFIG_32BIT)            += pmb.o
diff --git a/arch/sh/mm/cache-debugfs.c b/arch/sh/mm/cache-debugfs.c
new file mode 100644 (file)
index 0000000..a22d914
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * debugfs ops for the L1 cache
+ *
+ *  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/module.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+
+enum cache_type {
+       CACHE_TYPE_ICACHE,
+       CACHE_TYPE_DCACHE,
+       CACHE_TYPE_UNIFIED,
+};
+
+static int cache_seq_show(struct seq_file *file, void *iter)
+{
+       unsigned int cache_type = (unsigned int)file->private;
+       struct cache_info *cache;
+       unsigned int waysize, way, cache_size;
+       unsigned long ccr, base;
+       static unsigned long addrstart = 0;
+
+       /*
+        * Go uncached immediately so we don't skew the results any
+        * more than we already are..
+        */
+       jump_to_P2();
+
+       ccr = ctrl_inl(CCR);
+       if ((ccr & CCR_CACHE_ENABLE) == 0) {
+               back_to_P1();
+
+               seq_printf(file, "disabled\n");
+               return 0;
+       }
+
+       if (cache_type == CACHE_TYPE_DCACHE) {
+               base = CACHE_OC_ADDRESS_ARRAY;
+               cache = &cpu_data->dcache;
+       } else {
+               base = CACHE_IC_ADDRESS_ARRAY;
+               cache = &cpu_data->icache;
+       }
+
+       /*
+        * Due to the amount of data written out (depending on the cache size),
+        * we may be iterated over multiple times. In this case, keep track of
+        * the entry position in addrstart, and rewind it when we've hit the
+        * end of the cache.
+        *
+        * Likewise, the same code is used for multiple caches, so care must
+        * be taken for bouncing addrstart back and forth so the appropriate
+        * cache is hit.
+        */
+       cache_size = cache->ways * cache->sets * cache->linesz;
+       if (((addrstart & 0xff000000) != base) ||
+            (addrstart & 0x00ffffff) > cache_size)
+               addrstart = base;
+
+       waysize = cache->sets;
+
+       /*
+        * If the OC is already in RAM mode, we only have
+        * half of the entries to consider..
+        */
+       if ((ccr & CCR_CACHE_ORA) && cache_type == CACHE_TYPE_DCACHE)
+               waysize >>= 1;
+
+       waysize <<= cache->entry_shift;
+
+       for (way = 0; way < cache->ways; way++) {
+               unsigned long addr;
+               unsigned int line;
+
+               seq_printf(file, "-----------------------------------------\n");
+               seq_printf(file, "Way %d\n", way);
+               seq_printf(file, "-----------------------------------------\n");
+
+               for (addr = addrstart, line = 0;
+                    addr < addrstart + waysize;
+                    addr += cache->linesz, line++) {
+                       unsigned long data = ctrl_inl(addr);
+
+                       /* Check the V bit, ignore invalid cachelines */
+                       if ((data & 1) == 0)
+                               continue;
+
+                       /* U: Dirty, cache tag is 10 bits up */
+                       seq_printf(file, "%3d: %c 0x%lx\n",
+                                  line, data & 2 ? 'U' : ' ',
+                                  data & 0x1ffffc00);
+               }
+
+               addrstart += cache->way_incr;
+       }
+
+       back_to_P1();
+
+       return 0;
+}
+
+static int cache_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, cache_seq_show, inode->u.generic_ip);
+}
+
+static struct file_operations cache_debugfs_fops = {
+       .owner          = THIS_MODULE,
+       .open           = cache_debugfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int __init cache_debugfs_init(void)
+{
+       struct dentry *dcache_dentry, *icache_dentry;
+
+       dcache_dentry = debugfs_create_file("dcache", S_IRUSR, NULL,
+                                           (unsigned int *)CACHE_TYPE_DCACHE,
+                                           &cache_debugfs_fops);
+       if (IS_ERR(dcache_dentry))
+               return PTR_ERR(dcache_dentry);
+
+       icache_dentry = debugfs_create_file("icache", S_IRUSR, NULL,
+                                           (unsigned int *)CACHE_TYPE_ICACHE,
+                                           &cache_debugfs_fops);
+       if (IS_ERR(icache_dentry)) {
+               debugfs_remove(dcache_dentry);
+               return PTR_ERR(icache_dentry);
+       }
+
+       return 0;
+}
+module_init(cache_debugfs_init);
+
+MODULE_LICENSE("GPL v2");
index 524cea5b47f9ca7c93685a1d7bfa2746d49efc07..e48cc22724d9e8d7d215544b4904f977c2551418 100644 (file)
  * arch/sh/mm/cache-sh4.c
  *
  * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- * Copyright (C) 2001, 2002, 2003, 2004  Paul Mundt
+ * Copyright (C) 2001 - 2006  Paul Mundt
  * Copyright (C) 2003  Richard Curnow
  *
  * 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>
-#include <linux/threads.h>
 #include <asm/addrspace.h>
-#include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
-extern void __flush_cache_4096_all(unsigned long start);
-static void __flush_cache_4096_all_ex(unsigned long start);
-extern void __flush_dcache_all(void);
-static void __flush_dcache_all_ex(void);
+/*
+ * The maximum number of pages we support up to when doing ranged dcache
+ * flushing. Anything exceeding this will simply flush the dcache in its
+ * entirety.
+ */
+#define MAX_DCACHE_PAGES       64      /* XXX: Tune for ways */
+
+static void __flush_dcache_segment_1way(unsigned long start,
+                                       unsigned long extent);
+static void __flush_dcache_segment_2way(unsigned long start,
+                                       unsigned long extent);
+static void __flush_dcache_segment_4way(unsigned long start,
+                                       unsigned long extent);
+
+static void __flush_cache_4096(unsigned long addr, unsigned long phys,
+                              unsigned long exec_offset);
+
+/*
+ * This is initialised here to ensure that it is not placed in the BSS.  If
+ * that were to happen, note that cache_init gets called before the BSS is
+ * cleared, so this would get nulled out which would be hopeless.
+ */
+static void (*__flush_dcache_segment_fn)(unsigned long, unsigned long) =
+       (void (*)(unsigned long, unsigned long))0xdeadbeef;
+
+static void compute_alias(struct cache_info *c)
+{
+       c->alias_mask = ((c->sets - 1) << c->entry_shift) & ~(PAGE_SIZE - 1);
+       c->n_aliases = (c->alias_mask >> PAGE_SHIFT) + 1;
+}
+
+static void __init emit_cache_params(void)
+{
+       printk("PVR=%08x CVR=%08x PRR=%08x\n",
+               ctrl_inl(CCN_PVR),
+               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);
+       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);
+       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);
+       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);
+
+       if (!__flush_dcache_segment_fn)
+               panic("unknown number of cache ways\n");
+}
 
 /*
  * SH-4 has virtually indexed and physically tagged cache.
  */
 
-struct semaphore p3map_sem[4];
+/* Worst case assumed to be 64k cache, direct-mapped i.e. 4 synonym bits. */
+#define MAX_P3_SEMAPHORES 16
+
+struct semaphore p3map_sem[MAX_P3_SEMAPHORES];
 
 void __init p3_cache_init(void)
 {
-       if (remap_area_pages(P3SEG, 0, PAGE_SIZE*4, _PAGE_CACHABLE))
+       int i;
+
+       compute_alias(&cpu_data->icache);
+       compute_alias(&cpu_data->dcache);
+
+       switch (cpu_data->dcache.ways) {
+       case 1:
+               __flush_dcache_segment_fn = __flush_dcache_segment_1way;
+               break;
+       case 2:
+               __flush_dcache_segment_fn = __flush_dcache_segment_2way;
+               break;
+       case 4:
+               __flush_dcache_segment_fn = __flush_dcache_segment_4way;
+               break;
+       default:
+               __flush_dcache_segment_fn = NULL;
+               break;
+       }
+
+       emit_cache_params();
+
+       if (remap_area_pages(P3SEG, 0, PAGE_SIZE * 4, _PAGE_CACHABLE))
                panic("%s failed.", __FUNCTION__);
 
-       sema_init (&p3map_sem[0], 1);
-       sema_init (&p3map_sem[1], 1);
-       sema_init (&p3map_sem[2], 1);
-       sema_init (&p3map_sem[3], 1);
+       for (i = 0; i < cpu_data->dcache.n_aliases; i++)
+               sema_init(&p3map_sem[i], 1);
 }
 
 /*
@@ -89,7 +160,6 @@ void __flush_purge_region(void *start, int size)
        }
 }
 
-
 /*
  * No write back please
  */
@@ -108,40 +178,6 @@ void __flush_invalidate_region(void *start, int size)
        }
 }
 
-static void __flush_dcache_all_ex(void)
-{
-       unsigned long addr, end_addr, entry_offset;
-
-       end_addr = CACHE_OC_ADDRESS_ARRAY + (cpu_data->dcache.sets << cpu_data->dcache.entry_shift) * cpu_data->dcache.ways;
-       entry_offset = 1 << cpu_data->dcache.entry_shift;
-       for (addr = CACHE_OC_ADDRESS_ARRAY; addr < end_addr; addr += entry_offset) {
-               ctrl_outl(0, addr);
-       }
-}
-
-static void __flush_cache_4096_all_ex(unsigned long start)
-{
-       unsigned long addr, entry_offset;
-       int i;
-
-       entry_offset = 1 << cpu_data->dcache.entry_shift;
-       for (i = 0; i < cpu_data->dcache.ways; i++, start += cpu_data->dcache.way_incr) {
-               for (addr = CACHE_OC_ADDRESS_ARRAY + start;
-                    addr < CACHE_OC_ADDRESS_ARRAY + 4096 + start;
-                    addr += entry_offset) {
-                       ctrl_outl(0, addr);
-               }
-       }
-}
-
-void flush_cache_4096_all(unsigned long start)
-{
-       if (cpu_data->dcache.ways == 1)
-               __flush_cache_4096_all(start);
-       else
-               __flush_cache_4096_all_ex(start);
-}
-
 /*
  * Write back the range of D-cache, and purge the I-cache.
  *
@@ -153,14 +189,14 @@ void flush_icache_range(unsigned long start, unsigned long end)
 }
 
 /*
- * Write back the D-cache and purge the I-cache for signal trampoline. 
+ * Write back the D-cache and purge the I-cache for signal trampoline.
  * .. which happens to be the same behavior as flush_icache_range().
  * So, we simply flush out a line.
  */
 void flush_cache_sigtramp(unsigned long addr)
 {
        unsigned long v, index;
-       unsigned long flags; 
+       unsigned long flags;
        int i;
 
        v = addr & ~(L1_CACHE_BYTES-1);
@@ -172,30 +208,33 @@ void flush_cache_sigtramp(unsigned long addr)
 
        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 < cpu_data->icache.ways;
+            i++, index += cpu_data->icache.way_incr)
                ctrl_outl(0, index);    /* Clear out Valid-bit */
+
        back_to_P1();
+       wmb();
        local_irq_restore(flags);
 }
 
 static inline void flush_cache_4096(unsigned long start,
                                    unsigned long phys)
 {
-       unsigned long flags; 
-       extern void __flush_cache_4096(unsigned long addr, unsigned long phys, unsigned long exec_offset);
+       unsigned long flags, exec_offset = 0;
 
        /*
-        * SH7751, SH7751R, and ST40 have no restriction to handle cache.
-        * (While SH7750 must do that at P2 area.)
+        * 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)
-          || start < CACHE_OC_ADDRESS_ARRAY) {
-               local_irq_save(flags);
-               __flush_cache_4096(start | SH_CACHE_ASSOC, P1SEGADDR(phys), 0x20000000);
-               local_irq_restore(flags);
-       } else {
-               __flush_cache_4096(start | SH_CACHE_ASSOC, P1SEGADDR(phys), 0);
-       }
+       if ((cpu_data->flags & CPU_HAS_P2_FLUSH_BUG) ||
+           (start < CACHE_OC_ADDRESS_ARRAY))
+               exec_offset = 0x20000000;
+
+       local_irq_save(flags);
+       __flush_cache_4096(start | SH_CACHE_ASSOC,
+                          P1SEGADDR(phys), exec_offset);
+       local_irq_restore(flags);
 }
 
 /*
@@ -206,15 +245,19 @@ void flush_dcache_page(struct page *page)
 {
        if (test_bit(PG_mapped, &page->flags)) {
                unsigned long phys = PHYSADDR(page_address(page));
+               unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
+               int i, n;
 
                /* Loop all the D-cache */
-               flush_cache_4096(CACHE_OC_ADDRESS_ARRAY,          phys);
-               flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x1000, phys);
-               flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x2000, phys);
-               flush_cache_4096(CACHE_OC_ADDRESS_ARRAY | 0x3000, phys);
+               n = cpu_data->dcache.n_aliases;
+               for (i = 0; i < n; i++, addr += PAGE_SIZE)
+                       flush_cache_4096(addr, phys);
        }
+
+       wmb();
 }
 
+/* TODO: Selective icache invalidation through IC address array.. */
 static inline void flush_icache_all(void)
 {
        unsigned long flags, ccr;
@@ -227,34 +270,142 @@ static inline void flush_icache_all(void)
        ccr |= CCR_CACHE_ICI;
        ctrl_outl(ccr, CCR);
 
+       /*
+        * back_to_P1() will take care of the barrier for us, don't add
+        * another one!
+        */
+
        back_to_P1();
        local_irq_restore(flags);
 }
 
+void flush_dcache_all(void)
+{
+       (*__flush_dcache_segment_fn)(0UL, cpu_data->dcache.way_size);
+       wmb();
+}
+
 void flush_cache_all(void)
 {
-       if (cpu_data->dcache.ways == 1)
-               __flush_dcache_all();
-       else
-               __flush_dcache_all_ex();
+       flush_dcache_all();
        flush_icache_all();
 }
 
+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 select_bit;
+       unsigned long all_aliases_mask;
+       unsigned long addr_offset;
+       pgd_t *dir;
+       pmd_t *pmd;
+       pud_t *pud;
+       pte_t *pte;
+       int i;
+
+       dir = pgd_offset(mm, p);
+       pud = pud_offset(dir, p);
+       pmd = pmd_offset(pud, p);
+       end = PAGE_ALIGN(end);
+
+       all_aliases_mask = (1 << n_aliases) - 1;
+
+       do {
+               if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) {
+                       p &= PMD_MASK;
+                       p += PMD_SIZE;
+                       pmd++;
+
+                       continue;
+               }
+
+               pte = pte_offset_kernel(pmd, p);
+
+               do {
+                       unsigned long phys;
+                       pte_t entry = *pte;
+
+                       if (!(pte_val(entry) & _PAGE_PRESENT)) {
+                               pte++;
+                               p += PAGE_SIZE;
+                               continue;
+                       }
+
+                       phys = pte_val(entry) & PTE_PHYS_MASK;
+
+                       if ((p ^ phys) & alias_mask) {
+                               d |= 1 << ((p & alias_mask) >> PAGE_SHIFT);
+                               d |= 1 << ((phys & alias_mask) >> PAGE_SHIFT);
+
+                               if (d == all_aliases_mask)
+                                       goto loop_exit;
+                       }
+
+                       pte++;
+                       p += PAGE_SIZE;
+               } while (p < end && ((unsigned long)pte & ~PAGE_MASK));
+               pmd++;
+       } while (p < end);
+
+loop_exit:
+       addr_offset = 0;
+       select_bit = 1;
+
+       for (i = 0; i < n_aliases; i++) {
+               if (d & select_bit) {
+                       (*__flush_dcache_segment_fn)(addr_offset, PAGE_SIZE);
+                       wmb();
+               }
+
+               select_bit <<= 1;
+               addr_offset += PAGE_SIZE;
+       }
+}
+
+/*
+ * Note : (RPC) since the caches are physically tagged, the only point
+ * of flush_cache_mm for SH-4 is to get rid of aliases from the
+ * D-cache.  The assumption elsewhere, e.g. flush_cache_range, is that
+ * lines can stay resident so long as the virtual address they were
+ * accessed with (hence cache set) is in accord with the physical
+ * address (i.e. tag).  It's no different here.  So I reckon we don't
+ * need to flush the I-cache, since aliases don't matter for that.  We
+ * should try that.
+ *
+ * Caller takes mm->mmap_sem.
+ */
 void flush_cache_mm(struct mm_struct *mm)
 {
-       /* Is there any good way? */
-       /* XXX: possibly call flush_cache_range for each vm area */
-       /* 
-        * FIXME: Really, the optimal solution here would be able to flush out
-        * individual lines created by the specified context, but this isn't
-        * feasible for a number of architectures (such as MIPS, and some
-        * SPARC) .. is this possible for SuperH?
-        *
-        * In the meantime, we'll just flush all of the caches.. this
-        * seems to be the simplest way to avoid at least a few wasted
-        * cache flushes. -Lethal
+       /*
+        * 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.
         */
-       flush_cache_all();
+       if (cpu_data->dcache.n_aliases == 0)
+               return;
+
+       /*
+        * Don't bother groveling around the dcache for the VMA ranges
+        * if there are too many PTEs to make it worthwhile.
+        */
+       if (mm->nr_ptes >= MAX_DCACHE_PAGES)
+               flush_dcache_all();
+       else {
+               struct vm_area_struct *vma;
+
+               /*
+                * In this case there are reasonably sized ranges to flush,
+                * iterate through the VMA list and take care of any aliases.
+                */
+               for (vma = mm->mmap; vma; vma = vma->vm_next)
+                       __flush_cache_mm(mm, vma->vm_start, vma->vm_end);
+       }
+
+       /* Only touch the icache if one of the VMAs has VM_EXEC set. */
+       if (mm->exec_vm)
+               flush_icache_all();
 }
 
 /*
@@ -263,27 +414,40 @@ void flush_cache_mm(struct mm_struct *mm)
  * ADDR: Virtual Address (U0 address)
  * PFN: Physical page number
  */
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
+                     unsigned long pfn)
 {
        unsigned long phys = pfn << PAGE_SHIFT;
+       unsigned int alias_mask;
+
+       alias_mask = cpu_data->dcache.alias_mask;
 
        /* We only need to flush D-cache when we have alias */
-       if ((address^phys) & CACHE_ALIAS) {
+       if ((address^phys) & alias_mask) {
                /* Loop 4K of the D-cache */
                flush_cache_4096(
-                       CACHE_OC_ADDRESS_ARRAY | (address & CACHE_ALIAS),
+                       CACHE_OC_ADDRESS_ARRAY | (address & alias_mask),
                        phys);
                /* Loop another 4K of the D-cache */
                flush_cache_4096(
-                       CACHE_OC_ADDRESS_ARRAY | (phys & CACHE_ALIAS),
+                       CACHE_OC_ADDRESS_ARRAY | (phys & alias_mask),
                        phys);
        }
 
-       if (vma->vm_flags & VM_EXEC)
-               /* Loop 4K (half) of the I-cache */
+       alias_mask = cpu_data->icache.alias_mask;
+       if (vma->vm_flags & VM_EXEC) {
+               /*
+                * Evict entries from the portion of the cache from which code
+                * may have been executed at this address (virtual).  There's
+                * no need to evict from the portion corresponding to the
+                * physical address as for the D-cache, because we know the
+                * kernel has never executed the code through its identity
+                * translation.
+                */
                flush_cache_4096(
-                       CACHE_IC_ADDRESS_ARRAY | (address & 0x1000),
+                       CACHE_IC_ADDRESS_ARRAY | (address & alias_mask),
                        phys);
+       }
 }
 
 /*
@@ -298,52 +462,31 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigne
 void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
                       unsigned long end)
 {
-       unsigned long p = start & PAGE_MASK;
-       pgd_t *dir;
-       pmd_t *pmd;
-       pte_t *pte;
-       pte_t entry;
-       unsigned long phys;
-       unsigned long d = 0;
-
-       dir = pgd_offset(vma->vm_mm, p);
-       pmd = pmd_offset(dir, p);
+       /*
+        * 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)
+               return;
 
-       do {
-               if (pmd_none(*pmd) || pmd_bad(*pmd)) {
-                       p &= ~((1 << PMD_SHIFT) -1);
-                       p += (1 << PMD_SHIFT);
-                       pmd++;
-                       continue;
-               }
-               pte = pte_offset_kernel(pmd, p);
-               do {
-                       entry = *pte;
-                       if ((pte_val(entry) & _PAGE_PRESENT)) {
-                               phys = pte_val(entry)&PTE_PHYS_MASK;
-                               if ((p^phys) & CACHE_ALIAS) {
-                                       d |= 1 << ((p & CACHE_ALIAS)>>12); 
-                                       d |= 1 << ((phys & CACHE_ALIAS)>>12);
-                                       if (d == 0x0f)
-                                               goto loop_exit;
-                               }
-                       }
-                       pte++;
-                       p += PAGE_SIZE;
-               } while (p < end && ((unsigned long)pte & ~PAGE_MASK));
-               pmd++;
-       } while (p < end);
- loop_exit:
-       if (d & 1)
-               flush_cache_4096_all(0);
-       if (d & 2)
-               flush_cache_4096_all(0x1000);
-       if (d & 4)
-               flush_cache_4096_all(0x2000);
-       if (d & 8)
-               flush_cache_4096_all(0x3000);
-       if (vma->vm_flags & VM_EXEC)
+       /*
+        * Don't bother with the lookup and alias check if we have a
+        * wide range to cover, just blow away the dcache in its
+        * entirety instead. -- PFM.
+        */
+       if (((end - start) >> PAGE_SHIFT) >= MAX_DCACHE_PAGES)
+               flush_dcache_all();
+       else
+               __flush_cache_mm(vma->vm_mm, start, end);
+
+       if (vma->vm_flags & VM_EXEC) {
+               /*
+                * TODO: Is this required???  Need to look at how I-cache
+                * coherency is assured when new programs are loaded to see if
+                * this matters.
+                */
                flush_icache_all();
+       }
 }
 
 /*
@@ -357,5 +500,273 @@ void flush_icache_user_range(struct vm_area_struct *vma,
                             struct page *page, unsigned long addr, int len)
 {
        flush_cache_page(vma, addr, page_to_pfn(page));
+       mb();
+}
+
+/**
+ * __flush_cache_4096
+ *
+ * @addr:  address in memory mapped cache array
+ * @phys:  P1 address to flush (has to match tags if addr has 'A' bit
+ *         set i.e. associative write)
+ * @exec_offset: set to 0x20000000 if flush has to be executed from P2
+ *               region else 0x0
+ *
+ * The offset into the cache array implied by 'addr' selects the
+ * 'colour' of the virtual address range that will be flushed.  The
+ * operation (purge/write-back) is selected by the lower 2 bits of
+ * 'phys'.
+ */
+static void __flush_cache_4096(unsigned long addr, unsigned long phys,
+                              unsigned long exec_offset)
+{
+       int way_count;
+       unsigned long base_addr = addr;
+       struct cache_info *dcache;
+       unsigned long way_incr;
+       unsigned long a, ea, p;
+       unsigned long temp_pc;
+
+       dcache = &cpu_data->dcache;
+       /* Write this way for better assembly. */
+       way_count = dcache->ways;
+       way_incr = dcache->way_incr;
+
+       /*
+        * Apply exec_offset (i.e. branch to P2 if required.).
+        *
+        * FIXME:
+        *
+        *      If I write "=r" for the (temp_pc), it puts this in r6 hence
+        *      trashing exec_offset before it's been added on - why?  Hence
+        *      "=&r" as a 'workaround'
+        */
+       asm volatile("mov.l 1f, %0\n\t"
+                    "add   %1, %0\n\t"
+                    "jmp   @%0\n\t"
+                    "nop\n\t"
+                    ".balign 4\n\t"
+                    "1:  .long 2f\n\t"
+                    "2:\n" : "=&r" (temp_pc) : "r" (exec_offset));
+
+       /*
+        * We know there will be >=1 iteration, so write as do-while to avoid
+        * pointless nead-of-loop check for 0 iterations.
+        */
+       do {
+               ea = base_addr + PAGE_SIZE;
+               a = base_addr;
+               p = phys;
+
+               do {
+                       *(volatile unsigned long *)a = p;
+                       /*
+                        * Next line: intentionally not p+32, saves an add, p
+                        * will do since only the cache tag bits need to
+                        * match.
+                        */
+                       *(volatile unsigned long *)(a+32) = p;
+                       a += 64;
+                       p += 64;
+               } while (a < ea);
+
+               base_addr += way_incr;
+       } while (--way_count != 0);
 }
 
+/*
+ * Break the 1, 2 and 4 way variants of this out into separate functions to
+ * avoid nearly all the overhead of having the conditional stuff in the function
+ * bodies (+ the 1 and 2 way cases avoid saving any registers too).
+ */
+static void __flush_dcache_segment_1way(unsigned long start,
+                                       unsigned long extent_per_way)
+{
+       unsigned long orig_sr, sr_with_bl;
+       unsigned long base_addr;
+       unsigned long way_incr, linesz, way_size;
+       struct cache_info *dcache;
+       register unsigned long a0, a0e;
+
+       asm volatile("stc sr, %0" : "=r" (orig_sr));
+       sr_with_bl = orig_sr | (1<<28);
+       base_addr = ((unsigned long)&empty_zero_page[0]);
+
+       /*
+        * The previous code aligned base_addr to 16k, i.e. the way_size of all
+        * existing SH-4 D-caches.  Whilst I don't see a need to have this
+        * aligned to any better than the cache line size (which it will be
+        * anyway by construction), let's align it to at least the way_size of
+        * any existing or conceivable SH-4 D-cache.  -- RPC
+        */
+       base_addr = ((base_addr >> 16) << 16);
+       base_addr |= start;
+
+       dcache = &cpu_data->dcache;
+       linesz = dcache->linesz;
+       way_incr = dcache->way_incr;
+       way_size = dcache->way_size;
+
+       a0 = base_addr;
+       a0e = base_addr + extent_per_way;
+       do {
+               asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
+               asm volatile("movca.l r0, @%0\n\t"
+                            "ocbi @%0" : : "r" (a0));
+               a0 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "ocbi @%0" : : "r" (a0));
+               a0 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "ocbi @%0" : : "r" (a0));
+               a0 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "ocbi @%0" : : "r" (a0));
+               asm volatile("ldc %0, sr" : : "r" (orig_sr));
+               a0 += linesz;
+       } while (a0 < a0e);
+}
+
+static void __flush_dcache_segment_2way(unsigned long start,
+                                       unsigned long extent_per_way)
+{
+       unsigned long orig_sr, sr_with_bl;
+       unsigned long base_addr;
+       unsigned long way_incr, linesz, way_size;
+       struct cache_info *dcache;
+       register unsigned long a0, a1, a0e;
+
+       asm volatile("stc sr, %0" : "=r" (orig_sr));
+       sr_with_bl = orig_sr | (1<<28);
+       base_addr = ((unsigned long)&empty_zero_page[0]);
+
+       /* See comment under 1-way above */
+       base_addr = ((base_addr >> 16) << 16);
+       base_addr |= start;
+
+       dcache = &cpu_data->dcache;
+       linesz = dcache->linesz;
+       way_incr = dcache->way_incr;
+       way_size = dcache->way_size;
+
+       a0 = base_addr;
+       a1 = a0 + way_incr;
+       a0e = base_addr + extent_per_way;
+       do {
+               asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1" : :
+                            "r" (a0), "r" (a1));
+               a0 += linesz;
+               a1 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1" : :
+                            "r" (a0), "r" (a1));
+               a0 += linesz;
+               a1 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1" : :
+                            "r" (a0), "r" (a1));
+               a0 += linesz;
+               a1 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1" : :
+                            "r" (a0), "r" (a1));
+               asm volatile("ldc %0, sr" : : "r" (orig_sr));
+               a0 += linesz;
+               a1 += linesz;
+       } while (a0 < a0e);
+}
+
+static void __flush_dcache_segment_4way(unsigned long start,
+                                       unsigned long extent_per_way)
+{
+       unsigned long orig_sr, sr_with_bl;
+       unsigned long base_addr;
+       unsigned long way_incr, linesz, way_size;
+       struct cache_info *dcache;
+       register unsigned long a0, a1, a2, a3, a0e;
+
+       asm volatile("stc sr, %0" : "=r" (orig_sr));
+       sr_with_bl = orig_sr | (1<<28);
+       base_addr = ((unsigned long)&empty_zero_page[0]);
+
+       /* See comment under 1-way above */
+       base_addr = ((base_addr >> 16) << 16);
+       base_addr |= start;
+
+       dcache = &cpu_data->dcache;
+       linesz = dcache->linesz;
+       way_incr = dcache->way_incr;
+       way_size = dcache->way_size;
+
+       a0 = base_addr;
+       a1 = a0 + way_incr;
+       a2 = a1 + way_incr;
+       a3 = a2 + way_incr;
+       a0e = base_addr + extent_per_way;
+       do {
+               asm volatile("ldc %0, sr" : : "r" (sr_with_bl));
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "movca.l r0, @%2\n\t"
+                            "movca.l r0, @%3\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1\n\t"
+                            "ocbi @%2\n\t"
+                            "ocbi @%3\n\t" : :
+                            "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+               a0 += linesz;
+               a1 += linesz;
+               a2 += linesz;
+               a3 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "movca.l r0, @%2\n\t"
+                            "movca.l r0, @%3\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1\n\t"
+                            "ocbi @%2\n\t"
+                            "ocbi @%3\n\t" : :
+                            "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+               a0 += linesz;
+               a1 += linesz;
+               a2 += linesz;
+               a3 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "movca.l r0, @%2\n\t"
+                            "movca.l r0, @%3\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1\n\t"
+                            "ocbi @%2\n\t"
+                            "ocbi @%3\n\t" : :
+                            "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+               a0 += linesz;
+               a1 += linesz;
+               a2 += linesz;
+               a3 += linesz;
+               asm volatile("movca.l r0, @%0\n\t"
+                            "movca.l r0, @%1\n\t"
+                            "movca.l r0, @%2\n\t"
+                            "movca.l r0, @%3\n\t"
+                            "ocbi @%0\n\t"
+                            "ocbi @%1\n\t"
+                            "ocbi @%2\n\t"
+                            "ocbi @%3\n\t" : :
+                            "r" (a0), "r" (a1), "r" (a2), "r" (a3));
+               asm volatile("ldc %0, sr" : : "r" (orig_sr));
+               a0 += linesz;
+               a1 += linesz;
+               a2 += linesz;
+               a3 += linesz;
+       } while (a0 < a0e);
+}
index bf94eedb0a8e53e06fc0d0b88147aac636b80ad6..045abdf078f5bdc71a99c67f64da9c6cf76e6f4b 100644 (file)
@@ -9,7 +9,6 @@
  * for more details.
  *
  */
-
 #include <linux/init.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <asm/mmu_context.h>
 #include <asm/cacheflush.h>
 
-/* The 32KB cache on the SH7705 suffers from the same synonym problem
- * as SH4 CPUs */
-
-#define __pte_offset(address) \
-               ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-#define pte_offset(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \
-               __pte_offset(address))
-
+/*
+ * The 32KB cache on the SH7705 suffers from the same synonym problem
+ * as SH4 CPUs
+ */
 static inline void cache_wback_all(void)
 {
        unsigned long ways, waysize, addrstart;
@@ -73,7 +68,6 @@ void flush_icache_range(unsigned long start, unsigned long end)
        __flush_wback_region((void *)start, end - start);
 }
 
-
 /*
  * Writeback&Invalidate the D-cache of the page
  */
@@ -128,7 +122,6 @@ static void __flush_dcache_page(unsigned long phys)
        local_irq_restore(flags);
 }
 
-
 /*
  * Write back & invalidate the D-cache of the page.
  * (To avoid "alias" issues)
@@ -186,7 +179,8 @@ void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
  *
  * ADDRESS: Virtual Address (U0 address)
  */
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address,
+                     unsigned long pfn)
 {
        __flush_dcache_page(pfn << PAGE_SHIFT);
 }
@@ -203,4 +197,3 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page)
 {
        __flush_purge_region(page_address(page), PAGE_SIZE);
 }
-
index 08acead7b2a1b51070b1f2bf93259bfbd4b55523..7b96425ae270ec932b324465001f0d42eb15ff25 100644 (file)
@@ -193,102 +193,5 @@ ENTRY(__clear_user_page)
         nop
 .L4096:        .word   4096
 
-ENTRY(__flush_cache_4096)
-       mov.l   1f,r3
-       add     r6,r3
-       mov     r4,r0
-       mov     #64,r2
-       shll    r2
-       mov     #64,r6
-       jmp     @r3
-        mov    #96,r7
-       .align  2
-1:     .long   2f
-2:
-       .rept   32
-       mov.l   r5,@r0
-       mov.l   r5,@(32,r0)
-       mov.l   r5,@(r0,r6)
-       mov.l   r5,@(r0,r7)
-       add     r2,r5
-       add     r2,r0
-       .endr
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       nop
-       rts
-        nop
-
-ENTRY(__flush_dcache_all)
-       mov.l   2f,r0
-       mov.l   3f,r4
-       and     r0,r4           ! r4 = (unsigned long)&empty_zero_page[0] & ~0xffffc000
-       stc     sr,r1           ! save SR
-       mov.l   4f,r2
-       or      r1,r2
-       mov     #32,r3
-       shll2   r3
-1:
-       ldc     r2,sr           ! set BL bit
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       ldc     r1,sr           ! restore SR
-       dt      r3
-       bf/s    1b
-        add    #32,r4
-
-       rts
-        nop
-       .align  2
-2:     .long   0xffffc000
-3:     .long   empty_zero_page
-4:     .long   0x10000000      ! BL bit
-
-/* __flush_cache_4096_all(unsigned long addr) */
-ENTRY(__flush_cache_4096_all)
-       mov.l   2f,r0
-       mov.l   3f,r2
-       and     r0,r2
-       or      r2,r4           ! r4 = addr | (unsigned long)&empty_zero_page[0] & ~0x3fff
-       stc     sr,r1           ! save SR
-       mov.l   4f,r2
-       or      r1,r2
-       mov     #32,r3
-1:
-       ldc     r2,sr           ! set BL bit
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       add     #32,r4
-       movca.l r0,@r4
-       ocbi    @r4
-       ldc     r1,sr           ! restore SR
-       dt      r3
-       bf/s    1b
-        add    #32,r4
-
-       rts
-        nop
-       .align  2
-2:     .long   0xffffc000
-3:     .long   empty_zero_page
-4:     .long   0x10000000      ! BL bit
 #endif
+
index ee73e30263af947b683e2833bb88e52806151f21..c81e6b67ad300e9e8b23c5adfc1658184d1ea59e 100644 (file)
@@ -9,6 +9,8 @@
  */
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
+#include <asm/addrspace.h>
 #include <asm/io.h>
 
 void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
index 775f86cd3fe8f5930e85ef2b0b1337876f97d7eb..c69fd603226aa80a20ba084aebd545e65c5142c3 100644 (file)
@@ -1,33 +1,22 @@
-/* $Id: fault.c,v 1.14 2004/01/13 05:52:11 kkojima Exp $
+/*
+ * Page fault handler for SH with an MMU.
  *
- *  linux/arch/sh/mm/fault.c
  *  Copyright (C) 1999  Niibe Yutaka
  *  Copyright (C) 2003  Paul Mundt
  *
  *  Based on linux/arch/i386/mm/fault.c:
  *   Copyright (C) 1995  Linus Torvalds
+ *
+ * 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/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/module.h>
-
+#include <linux/hardirq.h>
+#include <linux/kprobes.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>
 #include <asm/kgdb.h>
 
 extern void die(const char *,struct pt_regs *,long);
@@ -187,18 +176,30 @@ do_sigbus:
                goto no_context;
 }
 
+#ifdef CONFIG_SH_STORE_QUEUES
 /*
- * Called with interrupt disabled.
+ * 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.
  */
-asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
-                              unsigned long address)
+#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)
 {
-       unsigned long addrmax = P4SEG;
        pgd_t *pgd;
+       pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;
        pte_t entry;
-       struct mm_struct *mm;
+       struct mm_struct *mm = current->mm;
        spinlock_t *ptl;
        int ret = 1;
 
@@ -207,31 +208,37 @@ asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
                kgdb_bus_err_hook();
 #endif
 
-#ifdef CONFIG_SH_STORE_QUEUES
-       addrmax = P4SEG_STORE_QUE + 0x04000000;
-#endif
-
-       if (address >= P3SEG && address < addrmax) {
+       /*
+        * 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 (address >= TASK_SIZE)
-               return 1;
-       else if (!(mm = current->mm))
-               return 1;
-       else
+       } else {
+               if (unlikely(address >= TASK_SIZE || !mm))
+                       return 1;
+
                pgd = pgd_offset(mm, address);
+       }
 
-       pmd = pmd_offset(pgd, 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 (pte_none(entry) || pte_not_present(entry)
-           || (writeaccess && !pte_write(entry)))
+       if (unlikely(pte_none(entry) || pte_not_present(entry)))
+               goto unlock;
+       if (unlikely(writeaccess && !pte_write(entry)))
                goto unlock;
 
        if (writeaccess)
@@ -243,13 +250,7 @@ asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
         * ITLB is not affected by "ldtlb" instruction.
         * So, we need to flush the entry by ourselves.
         */
-
-       {
-               unsigned long flags;
-               local_irq_save(flags);
-               __flush_tlb_page(get_asid(), address&PAGE_MASK);
-               local_irq_restore(flags);
-       }
+       __flush_tlb_page(get_asid(), address & PAGE_MASK);
 #endif
 
        set_pte(pte, entry);
@@ -260,121 +261,3 @@ unlock:
                pte_unmap_unlock(pte, ptl);
        return ret;
 }
-
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
-       if (vma->vm_mm && vma->vm_mm->context != NO_CONTEXT) {
-               unsigned long flags;
-               unsigned long asid;
-               unsigned long saved_asid = MMU_NO_ASID;
-
-               asid = vma->vm_mm->context & MMU_CONTEXT_ASID_MASK;
-               page &= PAGE_MASK;
-
-               local_irq_save(flags);
-               if (vma->vm_mm != current->mm) {
-                       saved_asid = get_asid();
-                       set_asid(asid);
-               }
-               __flush_tlb_page(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)
-{
-       struct mm_struct *mm = vma->vm_mm;
-
-       if (mm->context != 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 = NO_CONTEXT;
-                       if (mm == current->mm)
-                               activate_context(mm);
-               } else {
-                       unsigned long asid = mm->context&MMU_CONTEXT_ASID_MASK;
-                       unsigned long saved_asid = MMU_NO_ASID;
-
-                       start &= PAGE_MASK;
-                       end += (PAGE_SIZE - 1);
-                       end &= PAGE_MASK;
-                       if (mm != current->mm) {
-                               saved_asid = get_asid();
-                               set_asid(asid);
-                       }
-                       while (start < end) {
-                               __flush_tlb_page(asid, start);
-                               start += PAGE_SIZE;
-                       }
-                       if (saved_asid != MMU_NO_ASID)
-                               set_asid(saved_asid);
-               }
-               local_irq_restore(flags);
-       }
-}
-
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
-{
-       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();
-       } else {
-               unsigned long asid = init_mm.context&MMU_CONTEXT_ASID_MASK;
-               unsigned long saved_asid = get_asid();
-
-               start &= PAGE_MASK;
-               end += (PAGE_SIZE - 1);
-               end &= PAGE_MASK;
-               set_asid(asid);
-               while (start < end) {
-                       __flush_tlb_page(asid, start);
-                       start += PAGE_SIZE;
-               }
-               set_asid(saved_asid);
-       }
-       local_irq_restore(flags);
-}
-
-void flush_tlb_mm(struct mm_struct *mm)
-{
-       /* Invalidate all TLB of this process. */
-       /* Instead of invalidating each TLB, we get new MMU context. */
-       if (mm->context != NO_CONTEXT) {
-               unsigned long flags;
-
-               local_irq_save(flags);
-               mm->context = NO_CONTEXT;
-               if (mm == current->mm)
-                       activate_context(mm);
-               local_irq_restore(flags);
-       }
-}
-
-void flush_tlb_all(void)
-{
-       unsigned long flags, status;
-
-       /*
-        * Flush all the TLB.
-        *
-        * Write to the MMU control register's bit:
-        *      TF-bit for SH-3, TI-bit for SH-4.
-        *      It's same position, bit #2.
-        */
-       local_irq_save(flags);
-       status = ctrl_inl(MMUCR);
-       status |= 0x04;         
-       ctrl_outl(status, MMUCR);
-       local_irq_restore(flags);
-}
index 2a85bc15a41238ce2d84e5bf891b63b589bd67ae..329059d6b54a79b2bdfb2eacdb2c4477f5936386 100644 (file)
 pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
+       pud_t *pud;
        pmd_t *pmd;
        pte_t *pte = NULL;
 
        pgd = pgd_offset(mm, addr);
        if (pgd) {
-               pmd = pmd_alloc(mm, pgd, addr);
-               if (pmd)
-                       pte = pte_alloc_map(mm, pmd, addr);
+               pud = pud_alloc(mm, pgd, addr);
+               if (pud) {
+                       pmd = pmd_alloc(mm, pud, addr);
+                       if (pmd)
+                               pte = pte_alloc_map(mm, pmd, addr);
+               }
        }
+
        return pte;
 }
 
 pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
+       pud_t *pud;
        pmd_t *pmd;
        pte_t *pte = NULL;
 
        pgd = pgd_offset(mm, addr);
        if (pgd) {
-               pmd = pmd_offset(pgd, addr);
-               if (pmd)
-                       pte = pte_offset_map(pmd, addr);
-       }
-       return pte;
-}
-
-void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
-                    pte_t *ptep, pte_t entry)
-{
-       int i;
-
-       for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-               set_pte_at(mm, addr, ptep, entry);
-               ptep++;
-               addr += PAGE_SIZE;
-               pte_val(entry) += PAGE_SIZE;
+               pud = pud_offset(pgd, addr);
+               if (pud) {
+                       pmd = pmd_offset(pud, addr);
+                       if (pmd)
+                               pte = pte_offset_map(pmd, addr);
+               }
        }
-}
-
-pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
-                             pte_t *ptep)
-{
-       pte_t entry;
-       int i;
-
-       entry = *ptep;
 
-       for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-               pte_clear(mm, addr, ptep);
-               addr += PAGE_SIZE;
-               ptep++;
-       }
-
-       return entry;
+       return pte;
 }
 
 struct page *follow_huge_addr(struct mm_struct *mm,
index 8ea27ca4b700c1c080cfa3de90d9617f7a0b34a8..7154d1ce97859098b2c7647eee495c9fc13ef5d7 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/highmem.h>
 #include <linux/bootmem.h>
 #include <linux/pagemap.h>
-
+#include <linux/proc_fs.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -80,6 +80,7 @@ void show_mem(void)
 static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
 {
        pgd_t *pgd;
+       pud_t *pud;
        pmd_t *pmd;
        pte_t *pte;
 
@@ -89,7 +90,17 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
                return;
        }
 
-       pmd = pmd_offset(pgd, addr);
+       pud = pud_offset(pgd, addr);
+       if (pud_none(*pud)) {
+               pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC);
+               set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
+               if (pmd != pmd_offset(pud, 0)) {
+                       pud_ERROR(*pud);
+                       return;
+               }
+       }
+
+       pmd = pmd_offset(pud, addr);
        if (pmd_none(*pmd)) {
                pte = (pte_t *)get_zeroed_page(GFP_ATOMIC);
                set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
@@ -212,6 +223,8 @@ void __init paging_init(void)
        free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0);
 }
 
+static struct kcore_list kcore_mem, kcore_vmalloc;
+
 void __init mem_init(void)
 {
        extern unsigned long empty_zero_page[1024];
@@ -237,8 +250,13 @@ void __init mem_init(void)
         * Setup wrappers for copy/clear_page(), these will get overridden
         * later in the boot process if a better method is available.
         */
+#ifdef CONFIG_MMU
        copy_page = copy_page_slow;
        clear_page = clear_page_slow;
+#else
+       copy_page = copy_page_nommu;
+       clear_page = clear_page_nommu;
+#endif
 
        /* this will put all low memory onto the freelists */
        totalram_pages += free_all_bootmem_node(NODE_DATA(0));
@@ -254,7 +272,12 @@ void __init mem_init(void)
        datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
        initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
 
-       printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n",
+       kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
+       kclist_add(&kcore_vmalloc, (void *)VMALLOC_START,
+                  VMALLOC_END - VMALLOC_START);
+
+       printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, "
+              "%dk reserved, %dk data, %dk init)\n",
                (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
                max_mapnr << (PAGE_SHIFT-10),
                codesize >> 10,
@@ -263,6 +286,9 @@ void __init mem_init(void)
                initsize >> 10);
 
        p3_cache_init();
+
+       /* Initialize the vDSO */
+       vsyscall_init();
 }
 
 void free_initmem(void)
index 96fa4a999e2af1147b58c23ae4e04f8142a34b68..a9fe80cfc2338feaf2bbf2797b9988ac3982633a 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
@@ -134,6 +135,20 @@ void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
        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)
+        * in a non-translatable area, so mapping through page tables for
+        * this area is not only pointless, but also fundamentally
+        * broken. Just return the physical address instead.
+        *
+        * For boards that map a small PCI memory aperture somewhere in
+        * P1/P2 space, ioremap() will already do the right thing,
+        * and we'll never get this far.
+        */
+       if (is_pci_memaddr(phys_addr) && is_pci_memaddr(last_addr))
+               return (void __iomem *)phys_addr;
+
        /*
         * Don't allow anybody to remap normal RAM that we're using..
         */
@@ -192,7 +207,7 @@ void __iounmap(void __iomem *addr)
        unsigned long vaddr = (unsigned long __force)addr;
        struct vm_struct *p;
 
-       if (PXSEG(vaddr) < P3SEG)
+       if (PXSEG(vaddr) < P3SEG || is_pci_memaddr(vaddr))
                return;
 
 #ifdef CONFIG_32BIT
index 8f9165a4e333a32181c6cc4b678d2e4eacc42d7e..d15221beaa161ab555cb6b481268651d56570a4f 100644 (file)
 #include <linux/string.h>
 #include <asm/page.h>
 
-static void copy_page_nommu(void *to, void *from)
+void copy_page_nommu(void *to, void *from)
 {
        memcpy(to, from, PAGE_SIZE);
 }
 
-static void clear_page_nommu(void *to)
+void clear_page_nommu(void *to)
 {
        memset(to, 0, PAGE_SIZE);
 }
 
-static int __init pg_nommu_init(void)
+__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n)
 {
-       copy_page = copy_page_nommu;
-       clear_page = clear_page_nommu;
-
+       memcpy(to, from, n);
        return 0;
 }
 
-subsys_initcall(pg_nommu_init);
-
+__kernel_size_t __clear_user(void *to, __kernel_size_t n)
+{
+       memset(to, 0, n);
+       return 0;
+}
index c776b60fc25018ebfb0cf75e9976c603b65fdecd..07371ed7a31328e49fcf34377abc3b7b247cffb5 100644 (file)
@@ -2,7 +2,7 @@
  * arch/sh/mm/pg-sh4.c
  *
  * Copyright (C) 1999, 2000, 2002  Niibe Yutaka
- * Copyright (C) 2002  Paul Mundt
+ * Copyright (C) 2002 - 2005  Paul Mundt
  *
  * Released under the terms of the GNU GPL v2.0.
  */
@@ -23,6 +23,8 @@
 
 extern struct semaphore p3map_sem[];
 
+#define CACHE_ALIAS (cpu_data->dcache.alias_mask)
+
 /*
  * clear_user_page
  * @to: P1 address
@@ -35,14 +37,15 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
        if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0)
                clear_page(to);
        else {
-               pgprot_t pgprot = __pgprot(_PAGE_PRESENT | 
+               pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
                                           _PAGE_RW | _PAGE_CACHABLE |
-                                          _PAGE_DIRTY | _PAGE_ACCESSED | 
+                                          _PAGE_DIRTY | _PAGE_ACCESSED |
                                           _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
                unsigned long phys_addr = PHYSADDR(to);
                unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
-               pgd_t *dir = pgd_offset_k(p3_addr);
-               pmd_t *pmd = pmd_offset(dir, p3_addr);
+               pgd_t *pgd = pgd_offset_k(p3_addr);
+               pud_t *pud = pud_offset(pgd, p3_addr);
+               pmd_t *pmd = pmd_offset(pud, p3_addr);
                pte_t *pte = pte_offset_kernel(pmd, p3_addr);
                pte_t entry;
                unsigned long flags;
@@ -67,21 +70,22 @@ void clear_user_page(void *to, unsigned long address, struct page *page)
  * @address: U0 address to be mapped
  * @page: page (virt_to_page(to))
  */
-void copy_user_page(void *to, void *from, unsigned long address, 
+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 {
-               pgprot_t pgprot = __pgprot(_PAGE_PRESENT | 
+               pgprot_t pgprot = __pgprot(_PAGE_PRESENT |
                                           _PAGE_RW | _PAGE_CACHABLE |
-                                          _PAGE_DIRTY | _PAGE_ACCESSED | 
+                                          _PAGE_DIRTY | _PAGE_ACCESSED |
                                           _PAGE_HW_SHARED | _PAGE_FLAGS_HARD);
                unsigned long phys_addr = PHYSADDR(to);
                unsigned long p3_addr = P3SEG + (address & CACHE_ALIAS);
-               pgd_t *dir = pgd_offset_k(p3_addr);
-               pmd_t *pmd = pmd_offset(dir, p3_addr);
+               pgd_t *pgd = pgd_offset_k(p3_addr);
+               pud_t *pud = pud_offset(pgd, p3_addr);
+               pmd_t *pmd = pmd_offset(pud, p3_addr);
                pte_t *pte = pte_offset_kernel(pmd, p3_addr);
                pte_t entry;
                unsigned long flags;
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
new file mode 100644 (file)
index 0000000..92e7453
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * arch/sh/mm/pmb.c
+ *
+ * Privileged Space Mapping Buffer (PMB) Support.
+ *
+ * Copyright (C) 2005, 2006 Paul Mundt
+ *
+ * P1/P2 Section mapping definitions from map32.h, which was:
+ *
+ *     Copyright 2003 (c) Lineo Solutions,Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/err.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#include <asm/io.h>
+
+#define NR_PMB_ENTRIES 16
+
+static kmem_cache_t *pmb_cache;
+static unsigned long pmb_map;
+
+static struct pmb_entry pmb_init_map[] = {
+       /* vpn         ppn         flags (ub/sz/c/wt) */
+
+       /* P1 Section Mappings */
+       { 0x80000000, 0x00000000, PMB_SZ_64M  | PMB_C, },
+       { 0x84000000, 0x04000000, PMB_SZ_64M  | PMB_C, },
+       { 0x88000000, 0x08000000, PMB_SZ_128M | PMB_C, },
+       { 0x90000000, 0x10000000, PMB_SZ_64M  | PMB_C, },
+       { 0x94000000, 0x14000000, PMB_SZ_64M  | PMB_C, },
+       { 0x98000000, 0x18000000, PMB_SZ_64M  | PMB_C, },
+
+       /* P2 Section Mappings */
+       { 0xa0000000, 0x00000000, PMB_UB | PMB_SZ_64M  | PMB_WT, },
+       { 0xa4000000, 0x04000000, PMB_UB | PMB_SZ_64M  | PMB_WT, },
+       { 0xa8000000, 0x08000000, PMB_UB | PMB_SZ_128M | PMB_WT, },
+       { 0xb0000000, 0x10000000, PMB_UB | PMB_SZ_64M  | PMB_WT, },
+       { 0xb4000000, 0x14000000, PMB_UB | PMB_SZ_64M  | PMB_WT, },
+       { 0xb8000000, 0x18000000, PMB_UB | PMB_SZ_64M  | PMB_WT, },
+};
+
+static inline unsigned long mk_pmb_entry(unsigned int entry)
+{
+       return (entry & PMB_E_MASK) << PMB_E_SHIFT;
+}
+
+static inline unsigned long mk_pmb_addr(unsigned int entry)
+{
+       return mk_pmb_entry(entry) | PMB_ADDR;
+}
+
+static inline unsigned long mk_pmb_data(unsigned int entry)
+{
+       return mk_pmb_entry(entry) | PMB_DATA;
+}
+
+struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
+                           unsigned long flags)
+{
+       struct pmb_entry *pmbe;
+
+       pmbe = kmem_cache_alloc(pmb_cache, GFP_KERNEL);
+       if (!pmbe)
+               return ERR_PTR(-ENOMEM);
+
+       pmbe->vpn       = vpn;
+       pmbe->ppn       = ppn;
+       pmbe->flags     = flags;
+
+       return pmbe;
+}
+
+void pmb_free(struct pmb_entry *pmbe)
+{
+       kmem_cache_free(pmb_cache, pmbe);
+}
+
+/*
+ * Must be in P2 for __set_pmb_entry()
+ */
+int __set_pmb_entry(unsigned long vpn, unsigned long ppn,
+                   unsigned long flags, int *entry)
+{
+       unsigned int pos = *entry;
+
+       if (unlikely(pos == PMB_NO_ENTRY))
+               pos = find_first_zero_bit(&pmb_map, NR_PMB_ENTRIES);
+
+repeat:
+       if (unlikely(pos > NR_PMB_ENTRIES))
+               return -ENOSPC;
+
+       if (test_and_set_bit(pos, &pmb_map)) {
+               pos = find_first_zero_bit(&pmb_map, NR_PMB_ENTRIES);
+               goto repeat;
+       }
+
+       ctrl_outl(vpn | PMB_V, mk_pmb_addr(pos));
+
+#ifdef CONFIG_SH_WRITETHROUGH
+       /*
+        * When we are in 32-bit address extended mode, CCR.CB becomes
+        * invalid, so care must be taken to manually adjust cacheable
+        * translations.
+        */
+       if (likely(flags & PMB_C))
+               flags |= PMB_WT;
+#endif
+
+       ctrl_outl(ppn | flags | PMB_V, mk_pmb_data(pos));
+
+       *entry = pos;
+
+       return 0;
+}
+
+int set_pmb_entry(struct pmb_entry *pmbe)
+{
+       int ret;
+
+       jump_to_P2();
+       ret = __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &pmbe->entry);
+       back_to_P1();
+
+       return ret;
+}
+
+void clear_pmb_entry(struct pmb_entry *pmbe)
+{
+       unsigned int entry = pmbe->entry;
+       unsigned long addr;
+
+       /*
+        * Don't allow clearing of wired init entries, P1 or P2 access
+        * without a corresponding mapping in the PMB will lead to reset
+        * by the TLB.
+        */
+       if (unlikely(entry < ARRAY_SIZE(pmb_init_map) ||
+                    entry >= NR_PMB_ENTRIES))
+               return;
+
+       jump_to_P2();
+
+       /* Clear V-bit */
+       addr = mk_pmb_addr(entry);
+       ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr);
+
+       addr = mk_pmb_data(entry);
+       ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr);
+
+       back_to_P1();
+
+       clear_bit(entry, &pmb_map);
+}
+
+static DEFINE_SPINLOCK(pmb_list_lock);
+static struct pmb_entry *pmb_list;
+
+static inline void pmb_list_add(struct pmb_entry *pmbe)
+{
+       struct pmb_entry **p, *tmp;
+
+       p = &pmb_list;
+       while ((tmp = *p) != NULL)
+               p = &tmp->next;
+
+       pmbe->next = tmp;
+       *p = pmbe;
+}
+
+static inline void pmb_list_del(struct pmb_entry *pmbe)
+{
+       struct pmb_entry **p, *tmp;
+
+       for (p = &pmb_list; (tmp = *p); p = &tmp->next)
+               if (tmp == pmbe) {
+                       *p = tmp->next;
+                       return;
+               }
+}
+
+static struct {
+       unsigned long size;
+       int flag;
+} pmb_sizes[] = {
+       { .size = 0x20000000, .flag = PMB_SZ_512M, },
+       { .size = 0x08000000, .flag = PMB_SZ_128M, },
+       { .size = 0x04000000, .flag = PMB_SZ_64M,  },
+       { .size = 0x01000000, .flag = PMB_SZ_16M,  },
+};
+
+long pmb_remap(unsigned long vaddr, unsigned long phys,
+              unsigned long size, unsigned long flags)
+{
+       struct pmb_entry *pmbp;
+       unsigned long wanted;
+       int pmb_flags, i;
+
+       /* Convert typical pgprot value to the PMB equivalent */
+       if (flags & _PAGE_CACHABLE) {
+               if (flags & _PAGE_WT)
+                       pmb_flags = PMB_WT;
+               else
+                       pmb_flags = PMB_C;
+       } else
+               pmb_flags = PMB_WT | PMB_UB;
+
+       pmbp = NULL;
+       wanted = size;
+
+again:
+       for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++) {
+               struct pmb_entry *pmbe;
+               int ret;
+
+               if (size < pmb_sizes[i].size)
+                       continue;
+
+               pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag);
+               if (IS_ERR(pmbe))
+                       return PTR_ERR(pmbe);
+
+               ret = set_pmb_entry(pmbe);
+               if (ret != 0) {
+                       pmb_free(pmbe);
+                       return -EBUSY;
+               }
+
+               phys    += pmb_sizes[i].size;
+               vaddr   += pmb_sizes[i].size;
+               size    -= pmb_sizes[i].size;
+
+               /*
+                * Link adjacent entries that span multiple PMB entries
+                * for easier tear-down.
+                */
+               if (likely(pmbp))
+                       pmbp->link = pmbe;
+
+               pmbp = pmbe;
+       }
+
+       if (size >= 0x1000000)
+               goto again;
+
+       return wanted - size;
+}
+
+void pmb_unmap(unsigned long addr)
+{
+       struct pmb_entry **p, *pmbe;
+
+       for (p = &pmb_list; (pmbe = *p); p = &pmbe->next)
+               if (pmbe->vpn == addr)
+                       break;
+
+       if (unlikely(!pmbe))
+               return;
+
+       WARN_ON(!test_bit(pmbe->entry, &pmb_map));
+
+       do {
+               struct pmb_entry *pmblink = pmbe;
+
+               clear_pmb_entry(pmbe);
+               pmbe = pmblink->link;
+
+               pmb_free(pmblink);
+       } while (pmbe);
+}
+
+static void pmb_cache_ctor(void *pmb, kmem_cache_t *cachep, unsigned long flags)
+{
+       struct pmb_entry *pmbe = pmb;
+
+       memset(pmb, 0, sizeof(struct pmb_entry));
+
+       spin_lock_irq(&pmb_list_lock);
+
+       pmbe->entry = PMB_NO_ENTRY;
+       pmb_list_add(pmbe);
+
+       spin_unlock_irq(&pmb_list_lock);
+}
+
+static void pmb_cache_dtor(void *pmb, kmem_cache_t *cachep, unsigned long flags)
+{
+       spin_lock_irq(&pmb_list_lock);
+       pmb_list_del(pmb);
+       spin_unlock_irq(&pmb_list_lock);
+}
+
+static int __init pmb_init(void)
+{
+       unsigned int nr_entries = ARRAY_SIZE(pmb_init_map);
+       unsigned int entry;
+
+       BUG_ON(unlikely(nr_entries >= NR_PMB_ENTRIES));
+
+       pmb_cache = kmem_cache_create("pmb", sizeof(struct pmb_entry),
+                                     0, 0, pmb_cache_ctor, pmb_cache_dtor);
+       BUG_ON(!pmb_cache);
+
+       jump_to_P2();
+
+       /*
+        * Ordering is important, P2 must be mapped in the PMB before we
+        * can set PMB.SE, and P1 must be mapped before we jump back to
+        * P1 space.
+        */
+       for (entry = 0; entry < nr_entries; entry++) {
+               struct pmb_entry *pmbe = pmb_init_map + entry;
+
+               __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &entry);
+       }
+
+       ctrl_outl(0, PMB_IRMCR);
+
+       /* PMB.SE and UB[7] */
+       ctrl_outl((1 << 31) | (1 << 7), PMB_PASCR);
+
+       back_to_P1();
+
+       return 0;
+}
+arch_initcall(pmb_init);
+
+static int pmb_seq_show(struct seq_file *file, void *iter)
+{
+       int i;
+
+       seq_printf(file, "V: Valid, C: Cacheable, WT: Write-Through\n"
+                        "CB: Copy-Back, B: Buffered, UB: Unbuffered\n");
+       seq_printf(file, "ety   vpn  ppn  size   flags\n");
+
+       for (i = 0; i < NR_PMB_ENTRIES; i++) {
+               unsigned long addr, data;
+               unsigned int size;
+               char *sz_str = NULL;
+
+               addr = ctrl_inl(mk_pmb_addr(i));
+               data = ctrl_inl(mk_pmb_data(i));
+
+               size = data & PMB_SZ_MASK;
+               sz_str = (size == PMB_SZ_16M)  ? " 16MB":
+                        (size == PMB_SZ_64M)  ? " 64MB":
+                        (size == PMB_SZ_128M) ? "128MB":
+                                                "512MB";
+
+               /* 02: V 0x88 0x08 128MB C CB  B */
+               seq_printf(file, "%02d: %c 0x%02lx 0x%02lx %s %c %s %s\n",
+                          i, ((addr & PMB_V) && (data & PMB_V)) ? 'V' : ' ',
+                          (addr >> 24) & 0xff, (data >> 24) & 0xff,
+                          sz_str, (data & PMB_C) ? 'C' : ' ',
+                          (data & PMB_WT) ? "WT" : "CB",
+                          (data & PMB_UB) ? "UB" : " B");
+       }
+
+       return 0;
+}
+
+static int pmb_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, pmb_seq_show, NULL);
+}
+
+static struct file_operations pmb_debugfs_fops = {
+       .owner          = THIS_MODULE,
+       .open           = pmb_debugfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release,
+};
+
+static int __init pmb_debugfs_init(void)
+{
+       struct dentry *dentry;
+
+       dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
+                                    NULL, NULL, &pmb_debugfs_fops);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
+
+       return 0;
+}
+postcore_initcall(pmb_debugfs_init);
diff --git a/arch/sh/mm/tlb-flush.c b/arch/sh/mm/tlb-flush.c
new file mode 100644 (file)
index 0000000..73ec7f6
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * TLB flushing operations for SH with an MMU.
+ *
+ *  Copyright (C) 1999  Niibe Yutaka
+ *  Copyright (C) 2003  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 <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+       if (vma->vm_mm && vma->vm_mm->context.id != 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;
+               page &= PAGE_MASK;
+
+               local_irq_save(flags);
+               if (vma->vm_mm != current->mm) {
+                       saved_asid = get_asid();
+                       set_asid(asid);
+               }
+               __flush_tlb_page(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)
+{
+       struct mm_struct *mm = vma->vm_mm;
+
+       if (mm->context.id != 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;
+                       if (mm == current->mm)
+                               activate_context(mm);
+               } else {
+                       unsigned long asid;
+                       unsigned long saved_asid = MMU_NO_ASID;
+
+                       asid = mm->context.id & MMU_CONTEXT_ASID_MASK;
+                       start &= PAGE_MASK;
+                       end += (PAGE_SIZE - 1);
+                       end &= PAGE_MASK;
+                       if (mm != current->mm) {
+                               saved_asid = get_asid();
+                               set_asid(asid);
+                       }
+                       while (start < end) {
+                               __flush_tlb_page(asid, start);
+                               start += PAGE_SIZE;
+                       }
+                       if (saved_asid != MMU_NO_ASID)
+                               set_asid(saved_asid);
+               }
+               local_irq_restore(flags);
+       }
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+       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();
+       } else {
+               unsigned long asid;
+               unsigned long saved_asid = get_asid();
+
+               asid = init_mm.context.id & MMU_CONTEXT_ASID_MASK;
+               start &= PAGE_MASK;
+               end += (PAGE_SIZE - 1);
+               end &= PAGE_MASK;
+               set_asid(asid);
+               while (start < end) {
+                       __flush_tlb_page(asid, start);
+                       start += PAGE_SIZE;
+               }
+               set_asid(saved_asid);
+       }
+       local_irq_restore(flags);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+       /* Invalidate all TLB of this process. */
+       /* Instead of invalidating each TLB, we get new MMU context. */
+       if (mm->context.id != NO_CONTEXT) {
+               unsigned long flags;
+
+               local_irq_save(flags);
+               mm->context.id = NO_CONTEXT;
+               if (mm == current->mm)
+                       activate_context(mm);
+               local_irq_restore(flags);
+       }
+}
+
+void flush_tlb_all(void)
+{
+       unsigned long flags, status;
+
+       /*
+        * Flush all the TLB.
+        *
+        * Write to the MMU control register's bit:
+        *      TF-bit for SH-3, TI-bit for SH-4.
+        *      It's same position, bit #2.
+        */
+       local_irq_save(flags);
+       status = ctrl_inl(MMUCR);
+       status |= 0x04;
+       ctrl_outl(status, MMUCR);
+       ctrl_barrier();
+       local_irq_restore(flags);
+}
index 115b1b6be40b45c30c71b1413b4b6be8c1ef7cc7..812b2d567de2f6e57a7519864923a1bbd69bbfb9 100644 (file)
@@ -36,7 +36,6 @@ void update_mmu_cache(struct vm_area_struct * vma,
        unsigned long vpn;
        struct page *page;
        unsigned long pfn;
-       unsigned long ptea;
 
        /* Ptrace may call this routine. */
        if (vma && current->active_mm != vma->vm_mm)
@@ -59,10 +58,11 @@ void update_mmu_cache(struct vm_area_struct * vma,
        ctrl_outl(vpn, MMU_PTEH);
 
        pteval = pte_val(pte);
+
        /* Set PTEA register */
-       /* TODO: make this look less hacky */
-       ptea = ((pteval >> 28) & 0xe) | (pteval & 0x1);
-       ctrl_outl(ptea, MMU_PTEA);
+       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 */
index 686738d4aa3c295fe511878ec82cb99f69b400c8..1f25d9bb7538a511d3d9ff8d9d4dc88658d84b97 100644 (file)
@@ -7,7 +7,11 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
                timer_int.o )
 
 profdrvr-y                             := op_model_null.o
+
+# SH7750-style performance counters exist across 7750/7750S and 7091.
+profdrvr-$(CONFIG_CPU_SUBTYPE_SH7750S) := op_model_sh7750.o
 profdrvr-$(CONFIG_CPU_SUBTYPE_SH7750)  := op_model_sh7750.o
+profdrvr-$(CONFIG_CPU_SUBTYPE_SH7091)  := op_model_sh7750.o
 
 oprofile-y                             := $(DRIVER_OBJS) $(profdrvr-y)
 
index 182fe90925771cccbda3d51fa9d4160dd95a86f3..ac57638977ee639f332b541a9b2624a233a81d6d 100644 (file)
@@ -8,16 +8,15 @@
 SE                     SH_SOLUTION_ENGINE
 7751SE                 SH_7751_SOLUTION_ENGINE         
 7300SE                 SH_7300_SOLUTION_ENGINE
+7343SE                 SH_7343_SOLUTION_ENGINE
 73180SE                        SH_73180_SOLUTION_ENGINE
 7751SYSTEMH            SH_7751_SYSTEMH
 HP6XX                  SH_HP6XX
 HD64461                        HD64461
 HD64465                        HD64465
-SH2000                 SH_SH2000
 SATURN                 SH_SATURN
 DREAMCAST              SH_DREAMCAST
 BIGSUR                 SH_BIGSUR
-ADX                    SH_ADX
 MPC1211                        SH_MPC1211
 SNAPGEAR               SH_SECUREEDGE5410
 HS7751RVOIP            SH_HS7751RVOIP
@@ -25,4 +24,9 @@ RTS7751R2D            SH_RTS7751R2D
 EDOSK7705              SH_EDOSK7705
 SH4202_MICRODEV                SH_SH4202_MICRODEV
 SH03                   SH_SH03
-
+LANDISK                        SH_LANDISK
+R7780RP                        SH_R7780RP
+R7780MP                        SH_R7780MP
+TITAN                  SH_TITAN
+SHMIN                  SH_SHMIN
+7710VOIPGW             SH_7710VOIPGW
index 51cf6027b7014634ee8838d02288845933e6c5cb..0fbdaa5daa8cfbdd6f761481a93d3b1f7b95ff06 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
 # Linux kernel version: 2.6.18
-# Sat Sep 23 18:32:19 2006
+# Tue Sep 26 23:09:35 2006
 #
 CONFIG_SPARC=y
 CONFIG_SPARC64=y
@@ -141,6 +141,7 @@ CONFIG_SUN_AUXIO=y
 CONFIG_SUN_IO=y
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
+# CONFIG_PCI_MULTITHREAD_PROBE is not set
 # CONFIG_PCI_DEBUG is not set
 CONFIG_SUN_OPENPROMFS=m
 CONFIG_SPARC32_COMPAT=y
@@ -194,21 +195,9 @@ CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
-CONFIG_TCP_CONG_ADVANCED=y
-
-#
-# TCP congestion control
-#
-CONFIG_TCP_CONG_BIC=y
-CONFIG_TCP_CONG_CUBIC=m
-CONFIG_TCP_CONG_WESTWOOD=m
-CONFIG_TCP_CONG_HTCP=m
-CONFIG_TCP_CONG_HSTCP=m
-CONFIG_TCP_CONG_HYBLA=m
-CONFIG_TCP_CONG_VEGAS=m
-CONFIG_TCP_CONG_SCALABLE=m
-CONFIG_TCP_CONG_LP=m
-CONFIG_TCP_CONG_VENO=m
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
 CONFIG_IPV6=m
 CONFIG_IPV6_PRIVACY=y
 CONFIG_IPV6_ROUTER_PREF=y
@@ -247,6 +236,7 @@ CONFIG_IP_DCCP_TFRC_LIB=m
 # DCCP Kernel Hacking
 #
 # CONFIG_IP_DCCP_DEBUG is not set
+# CONFIG_NET_DCCPPROBE is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -401,6 +391,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 CONFIG_RAID_ATTRS=m
 CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
 CONFIG_SCSI_PROC_FS=y
 
 #
@@ -422,12 +413,13 @@ CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 CONFIG_SCSI_ISCSI_ATTRS=m
 # CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -440,16 +432,18 @@ CONFIG_ISCSI_TCP=m
 # 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_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_MEGARAID_SAS is not set
-# CONFIG_SCSI_SATA 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
@@ -461,6 +455,11 @@ CONFIG_ISCSI_TCP=m
 # CONFIG_SCSI_DEBUG is not set
 # CONFIG_SCSI_SUNESP is not set
 
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
 #
 # Multi-device support (RAID and LVM)
 #
@@ -575,6 +574,7 @@ CONFIG_E1000_NAPI=y
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=m
 CONFIG_BNX2=m
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -1006,6 +1006,7 @@ CONFIG_SND_ALI5451=m
 # CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
 # CONFIG_SND_YMFPCI is not set
+# CONFIG_SND_AC97_POWER_SAVE is not set
 
 #
 # USB devices
@@ -1353,6 +1354,7 @@ CONFIG_KPROBES=y
 # Kernel hacking
 #
 CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_KERNEL=y
index c88ae23ce81230709d491888bdfb6542d7c24705..69444f266e2d5b88526b7019f3a0529de80edd9d 100644 (file)
@@ -1016,7 +1016,7 @@ struct __sysctl_args32 {
 
 asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
 {
-#ifndef CONFIG_SYSCTL
+#ifndef CONFIG_SYSCTL_SYSCALL
        return -ENOSYS;
 #else
        struct __sysctl_args32 tmp;
index dcba4e6ab5702d675365c5ec56a77866ddad4dde..09cb7fccc03a758ca2e0f8351734e8a550830c02 100644 (file)
@@ -920,8 +920,7 @@ static unsigned long __init bootmem_init(unsigned long *pages_avail,
        if (sparc_ramdisk_image || sparc_ramdisk_image64) {
                unsigned long ramdisk_image = sparc_ramdisk_image ?
                        sparc_ramdisk_image : sparc_ramdisk_image64;
-               if (ramdisk_image >= (unsigned long)_end - 2 * PAGE_SIZE)
-                       ramdisk_image -= KERNBASE;
+               ramdisk_image -= KERNBASE;
                initrd_start = ramdisk_image + phys_base;
                initrd_end = initrd_start + sparc_ramdisk_size;
                if (initrd_end > end_of_phys_memory) {
index 9558a7cf34d599f8eda369838ffda69bba6ec646..11154b6773ec230302341d8889e79601677b47c1 100644 (file)
@@ -4,10 +4,13 @@
 core-y += arch/um/sys-x86_64/
 START := 0x60000000
 
+_extra_flags_ = -fno-builtin -m64 -mcmodel=kernel
+
 #We #undef __x86_64__ for kernelspace, not for userspace where
 #it's needed for headers to work!
-CFLAGS += -U__$(SUBARCH)__ -fno-builtin -m64
-USER_CFLAGS += -fno-builtin -m64
+CFLAGS += -U__$(SUBARCH)__ $(_extra_flags_)
+USER_CFLAGS += $(_extra_flags_)
+
 CHECKFLAGS  += -m64
 AFLAGS += -m64
 LDFLAGS += -m elf_x86_64
index e82764f75e7f149c5144f3d4d984c9cac990c06b..3576b3cc505e65432a3068dbce33f6aecc1f666b 100644 (file)
@@ -110,7 +110,7 @@ static void not_configged_free(void *data)
               "UML\n");
 }
 
-static struct chan_ops not_configged_ops = {
+static const struct chan_ops not_configged_ops = {
        .init           = not_configged_init,
        .open           = not_configged_open,
        .close          = not_configged_close,
@@ -373,7 +373,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
 }
 
 int console_open_chan(struct line *line, struct console *co,
-                     struct chan_opts *opts)
+                     const struct chan_opts *opts)
 {
        int err;
 
@@ -494,10 +494,10 @@ int chan_config_string(struct list_head *chans, char *str, int size,
 
 struct chan_type {
        char *key;
-       struct chan_ops *ops;
+       const struct chan_ops *ops;
 };
 
-static struct chan_type chan_table[] = {
+static const struct chan_type chan_table[] = {
        { "fd", &fd_ops },
 
 #ifdef CONFIG_NULL_CHAN
@@ -534,10 +534,10 @@ static struct chan_type chan_table[] = {
 };
 
 static struct chan *parse_chan(struct line *line, char *str, int device,
-                              struct chan_opts *opts)
+                              const struct chan_opts *opts)
 {
-       struct chan_type *entry;
-       struct chan_ops *ops;
+       const struct chan_type *entry;
+       const struct chan_ops *ops;
        struct chan *chan;
        void *data;
        int i;
@@ -582,7 +582,7 @@ static struct chan *parse_chan(struct line *line, char *str, int device,
 }
 
 int parse_chan_pair(char *str, struct line *line, int device,
-                   struct chan_opts *opts)
+                   const struct chan_opts *opts)
 {
        struct list_head *chans = &line->chan_list;
        struct chan *new, *chan;
index 7326c42f7ef9c9572c1f32488c3ffc2df117afc6..3bc3cf6b94aaf41b2e7e64eeff26ddaa74d36626 100644 (file)
@@ -18,7 +18,7 @@ struct daemon_data {
        void *dev;
 };
 
-extern struct net_user_info daemon_user_info;
+extern const struct net_user_info daemon_user_info;
 
 extern int daemon_user_write(int fd, void *buf, int len, 
                             struct daemon_data *pri);
index 53d09ed78b425391c3e118f998fcd0f89a146691..824386974f88902469f2d95713ae9e4bf6a2928f 100644 (file)
@@ -57,7 +57,7 @@ static int daemon_write(int fd, struct sk_buff **skb,
                                 (struct daemon_data *) &lp->user));
 }
 
-static struct net_kern_info daemon_kern_info = {
+static const struct net_kern_info daemon_kern_info = {
        .init                   = daemon_init,
        .protocol               = eth_protocol,
        .read                   = daemon_read,
index c944265955e203f9a11892f2283e3900aebcef11..77954ea77043796217b22f83e3ef0d9d3b8c7c14 100644 (file)
@@ -182,7 +182,7 @@ static int daemon_set_mtu(int mtu, void *data)
        return(mtu);
 }
 
-struct net_user_info daemon_user_info = {
+const struct net_user_info daemon_user_info = {
        .init           = daemon_user_init,
        .open           = daemon_open,
        .close          = NULL,
index c41f75e4acb5a64d733af6534837026421f52037..108b7dafbd0e99a6d0cf9a9d82ca26ed6d1ac5f1 100644 (file)
@@ -20,7 +20,7 @@ struct fd_chan {
        char str[sizeof("1234567890\0")];
 };
 
-static void *fd_init(char *str, int device, struct chan_opts *opts)
+static void *fd_init(char *str, int device, const struct chan_opts *opts)
 {
        struct fd_chan *data;
        char *end;
@@ -77,7 +77,7 @@ static void fd_close(int fd, void *d)
        }
 }
 
-struct chan_ops fd_ops = {
+const struct chan_ops fd_ops = {
        .type           = "fd",
        .init           = fd_init,
        .open           = fd_open,
index 37232f908cd74e1c86e88874f68f41bb342fabcf..d247ef45c374c3cb620f6e741035c310f428d4d6 100644 (file)
@@ -280,7 +280,7 @@ static int hostmixer_release(struct inode *inode, struct file *file)
 
 /* kernel module operations */
 
-static struct file_operations hostaudio_fops = {
+static const struct file_operations hostaudio_fops = {
         .owner          = THIS_MODULE,
         .llseek         = no_llseek,
         .read           = hostaudio_read,
@@ -292,7 +292,7 @@ static struct file_operations hostaudio_fops = {
         .release        = hostaudio_release,
 };
 
-static struct file_operations hostmixer_fops = {
+static const struct file_operations hostmixer_fops = {
         .owner          = THIS_MODULE,
         .llseek         = no_llseek,
         .ioctl          = hostmixer_ioctl_mixdev,
index ebebaabb78ad75150ff818cd092f7c918b3fe7dd..563ce7690a1eb66ccf38376da5c68c591666a7ea 100644 (file)
@@ -251,7 +251,7 @@ void line_set_termios(struct tty_struct *tty, struct termios * old)
        /* nothing */
 }
 
-static struct {
+static const struct {
        int  cmd;
        char *level;
        char *name;
@@ -405,7 +405,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
 
 int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
 {
-       struct line_driver *driver = line->driver;
+       const struct line_driver *driver = line->driver;
        int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM;
 
        if (input)
@@ -558,7 +558,7 @@ int line_setup(struct line *lines, unsigned int num, char *init)
 }
 
 int line_config(struct line *lines, unsigned int num, char *str,
-               struct chan_opts *opts)
+               const struct chan_opts *opts)
 {
        struct line *line;
        char *new;
index a2c6db243458972a7eb8dab4c244d29cb0f685b9..bc56af9d3e534a6d4fb874597d2a719564ad5f26 100644 (file)
@@ -13,7 +13,7 @@ struct mcast_data {
        void *dev;
 };
 
-extern struct net_user_info mcast_user_info;
+extern const struct net_user_info mcast_user_info;
 
 extern int mcast_user_write(int fd, void *buf, int len, 
                            struct mcast_data *pri);
index 3a7af18cf9442f1c890ea674d9a8f33784a825a4..c090fbd464e7c9c7713d0eb6456aa859d69eb831 100644 (file)
@@ -61,7 +61,7 @@ static int mcast_write(int fd, struct sk_buff **skb,
                                 (struct mcast_data *) &lp->user);
 }
 
-static struct net_kern_info mcast_kern_info = {
+static const struct net_kern_info mcast_kern_info = {
        .init                   = mcast_init,
        .protocol               = eth_protocol,
        .read                   = mcast_read,
index afe85bfa66e0872eabc55cd1e0b25dace52900bc..4d2bd39a85bc16ff7dc685b908dad366fa82cac0 100644 (file)
@@ -152,7 +152,7 @@ static int mcast_set_mtu(int mtu, void *data)
        return(mtu);
 }
 
-struct net_user_info mcast_user_info = {
+const struct net_user_info mcast_user_info = {
        .init           = mcast_user_init,
        .open           = mcast_open,
        .close          = mcast_close,
index 022f67bb687364f2934b388fca57f703f53c2bfe..9a3b5daf6250784c1359f8997e115eac3ab8f29b 100644 (file)
@@ -85,7 +85,7 @@ mmapper_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static struct file_operations mmapper_fops = {
+static const struct file_operations mmapper_fops = {
        .owner          = THIS_MODULE,
        .read           = mmapper_read,
        .write          = mmapper_write,
@@ -95,7 +95,7 @@ static struct file_operations mmapper_fops = {
        .release        = mmapper_release,
 };
 
-static struct miscdevice mmapper_dev = {
+static const struct miscdevice mmapper_dev = {
        .minor          = MISC_DYNAMIC_MINOR,
        .name           = "mmapper",
        .fops           = &mmapper_fops
index 4a7966b219317440b991de2961130add5d94299d..664c2e2fb8209de464e27a951407e7d9fb58ae56 100644 (file)
@@ -114,8 +114,6 @@ static int uml_net_open(struct net_device *dev)
        struct uml_net_private *lp = dev->priv;
        int err;
 
-       spin_lock(&lp->lock);
-
        if(lp->fd >= 0){
                err = -ENXIO;
                goto out;
@@ -149,8 +147,6 @@ static int uml_net_open(struct net_device *dev)
         */
        while((err = uml_net_rx(dev)) > 0) ;
 
-       spin_unlock(&lp->lock);
-
        spin_lock(&opened_lock);
        list_add(&lp->list, &opened);
        spin_unlock(&opened_lock);
@@ -160,7 +156,6 @@ out_close:
        if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
        lp->fd = -1;
 out:
-       spin_unlock(&lp->lock);
        return err;
 }
 
@@ -169,15 +164,12 @@ static int uml_net_close(struct net_device *dev)
        struct uml_net_private *lp = dev->priv;
        
        netif_stop_queue(dev);
-       spin_lock(&lp->lock);
 
        free_irq(dev->irq, dev);
        if(lp->close != NULL)
                (*lp->close)(lp->fd, &lp->user);
        lp->fd = -1;
 
-       spin_unlock(&lp->lock);
-
        spin_lock(&opened_lock);
        list_del(&lp->list);
        spin_unlock(&opened_lock);
@@ -246,9 +238,9 @@ static int uml_net_set_mac(struct net_device *dev, void *addr)
        struct uml_net_private *lp = dev->priv;
        struct sockaddr *hwaddr = addr;
 
-       spin_lock(&lp->lock);
+       spin_lock_irq(&lp->lock);
        set_ether_mac(dev, hwaddr->sa_data);
-       spin_unlock(&lp->lock);
+       spin_unlock_irq(&lp->lock);
 
        return(0);
 }
@@ -258,7 +250,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
        struct uml_net_private *lp = dev->priv;
        int err = 0;
 
-       spin_lock(&lp->lock);
+       spin_lock_irq(&lp->lock);
 
        new_mtu = (*lp->set_mtu)(new_mtu, &lp->user);
        if(new_mtu < 0){
@@ -269,7 +261,7 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
        dev->mtu = new_mtu;
 
  out:
-       spin_unlock(&lp->lock);
+       spin_unlock_irq(&lp->lock);
        return err;
 }
 
@@ -569,12 +561,13 @@ static int eth_setup(char *str)
        int n, err;
 
        err = eth_parse(str, &n, &str);
-       if(err) return(1);
+       if(err)
+               return 1;
 
-       new = alloc_bootmem(sizeof(new));
+       new = alloc_bootmem(sizeof(*new));
        if (new == NULL){
                printk("eth_init : alloc_bootmem failed\n");
-               return(1);
+               return 1;
        }
 
        INIT_LIST_HEAD(&new->list);
@@ -582,7 +575,7 @@ static int eth_setup(char *str)
        new->init = str;
 
        list_add_tail(&new->list, &eth_cmd_line);
-       return(1);
+       return 1;
 }
 
 __setup("eth", eth_setup);
index 14cc5f78398ad4363968278ba30e2dbe981e30e4..3683ed44315d6e2da21707c9293bf82eb22e326b 100644 (file)
@@ -10,7 +10,7 @@
 
 static int null_chan;
 
-static void *null_init(char *str, int device, struct chan_opts *opts)
+static void *null_init(char *str, int device, const struct chan_opts *opts)
 {
        return(&null_chan);
 }
@@ -31,7 +31,7 @@ static void null_free(void *data)
 {
 }
 
-struct chan_ops null_ops = {
+const struct chan_ops null_ops = {
        .type           = "null",
        .init           = null_init,
        .open           = null_open,
index 4c767c7adb964d5546383a4b20e57302334efc2a..6e1ef8558283254faf6c28f462cf71b90cb6626f 100644 (file)
@@ -46,7 +46,7 @@ static int pcap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
        return(-EPERM);
 }
 
-static struct net_kern_info pcap_kern_info = {
+static const struct net_kern_info pcap_kern_info = {
        .init                   = pcap_init,
        .protocol               = eth_protocol,
        .read                   = pcap_read,
index edfcb29273e1abf19f601d523a4b125cdc35289f..2ef641ded960a96670456b5d2f1b56914a689c42 100644 (file)
@@ -120,7 +120,7 @@ int pcap_user_read(int fd, void *buffer, int len, struct pcap_data *pri)
        return(hdata.len);
 }
 
-struct net_user_info pcap_user_info = {
+const struct net_user_info pcap_user_info = {
        .init           = pcap_user_init,
        .open           = pcap_open,
        .close          = NULL,
index c43e8bb3250264940af52ea528fe6a378fe41f67..f2e8fc42ecc2df4a2ec7bfe247ab7ec12fe1659c 100644 (file)
@@ -27,7 +27,7 @@ struct port_chan {
        char dev[sizeof("32768\0")];
 };
 
-static void *port_init(char *str, int device, struct chan_opts *opts)
+static void *port_init(char *str, int device, const struct chan_opts *opts)
 {
        struct port_chan *data;
        void *kern_data;
@@ -100,7 +100,7 @@ static void port_close(int fd, void *d)
        os_close_file(fd);
 }
 
-struct chan_ops port_ops = {
+const struct chan_ops port_ops = {
        .type           = "port",
        .init           = port_init,
        .open           = port_open,
index 1c555c38de4d0184adb129755058b71a1449553f..abec620e838030d43e7a01626cb82c5c041ed63f 100644 (file)
@@ -22,7 +22,7 @@ struct pty_chan {
        char dev_name[sizeof("/dev/pts/0123456\0")];
 };
 
-static void *pty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *pty_chan_init(char *str, int device, const struct chan_opts *opts)
 {
        struct pty_chan *data;
 
@@ -118,7 +118,7 @@ static int pty_open(int input, int output, int primary, void *d,
        return(fd);
 }
 
-struct chan_ops pty_ops = {
+const struct chan_ops pty_ops = {
        .type           = "pty",
        .init           = pty_chan_init,
        .open           = pty_open,
@@ -131,7 +131,7 @@ struct chan_ops pty_ops = {
        .winch          = 0,
 };
 
-struct chan_ops pts_ops = {
+const struct chan_ops pts_ops = {
        .type           = "pts",
        .init           = pty_chan_init,
        .open           = pts_open,
index ba471f5864a6d7d6815f3847a36aa78b4ed1a5e3..ae9909415b9cdb372c1f1f0c1602a21a4c2e86b3 100644 (file)
@@ -68,7 +68,7 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
        return ret;
 }
 
-static struct file_operations rng_chrdev_ops = {
+static const struct file_operations rng_chrdev_ops = {
        .owner          = THIS_MODULE,
        .open           = rng_dev_open,
        .read           = rng_dev_read,
index bb0dab41c2e43a464f5e7dbfe15c28aca84a197c..c64f8c61d2743bc7a75cfea4712a40a3063eb128 100644 (file)
@@ -12,7 +12,7 @@ struct slip_data {
        struct slip_proto slip;
 };
 
-extern struct net_user_info slip_user_info;
+extern const struct net_user_info slip_user_info;
 
 extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri);
 extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri);
index 163ee0d5f75e4e165c312a47b02d2af8975f4be9..ccea2d7885e58d2937df864a30e61db69d3f7b77 100644 (file)
@@ -61,7 +61,7 @@ static int slip_write(int fd, struct sk_buff **skb,
                               (struct slip_data *) &lp->user));
 }
 
-struct net_kern_info slip_kern_info = {
+const struct net_kern_info slip_kern_info = {
        .init                   = slip_init,
        .protocol               = slip_protocol,
        .read                   = slip_read,
index 89fbec185cc16ec10d2d8df49410cf8bb32080a1..8460285c69a5cea3e0b842d0b5cd792d84c38aef 100644 (file)
@@ -241,7 +241,7 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask,
        close_addr(addr, netmask, pri->name);
 }
 
-struct net_user_info slip_user_info = {
+const struct net_user_info slip_user_info = {
        .init           = slip_user_init,
        .open           = slip_open,
        .close          = slip_close,
index 6cf88ab580c99a7828fbf545fa8b427ec8b862b5..89ccf83b757718b7c4617df8d1e223138a5a2f39 100644 (file)
@@ -24,7 +24,7 @@ struct slirp_data {
        struct slip_proto slip;
 };
 
-extern struct net_user_info slirp_user_info;
+extern const struct net_user_info slirp_user_info;
 
 extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri);
 extern int slirp_user_write(int fd, void *buf, int len,
index 95e50c943e14f52c7770be2788d5f598cab64adf..ae322e1c8a8753e3794c18cafa20d5d3af6d9b2d 100644 (file)
@@ -64,7 +64,7 @@ static int slirp_write(int fd, struct sk_buff **skb,
                               (struct slirp_data *) &lp->user));
 }
 
-struct net_kern_info slirp_kern_info = {
+const struct net_kern_info slirp_kern_info = {
        .init                   = slirp_init,
        .protocol               = slirp_protocol,
        .read                   = slirp_read,
index 33c5f6e625e83eecc26a97b774dffa6fe1bbb750..ce5e85d1de3d8029ca968033d2d66117de66abcf 100644 (file)
@@ -126,7 +126,7 @@ static int slirp_set_mtu(int mtu, void *data)
        return(mtu);
 }
 
-struct net_user_info slirp_user_info = {
+const struct net_user_info slirp_user_info = {
        .init           = slirp_user_init,
        .open           = slirp_open,
        .close          = slirp_close,
index 6dafd6fbfdaed13be0f48424f1e811fd24955b89..6f13e7c71a82f3ecb00ccf44e24c0cfc8fafc9fd 100644 (file)
@@ -23,7 +23,7 @@
 #include "irq_user.h"
 #include "mconsole_kern.h"
 
-static int ssl_version = 1;
+static const int ssl_version = 1;
 
 /* Referenced only by tty_driver below - presumably it's locked correctly
  * by the tty driver.
@@ -123,7 +123,7 @@ void ssl_hangup(struct tty_struct *tty)
 }
 #endif
 
-static struct tty_operations ssl_ops = {
+static const struct tty_operations ssl_ops = {
        .open                   = ssl_open,
        .close                  = line_close,
        .write                  = line_write,
index 856f568c2687fd485a111d2f68843bb3918ac7dc..5e44adb07051723333236caa67d9358e2cb7aabc 100644 (file)
@@ -110,7 +110,7 @@ static int con_open(struct tty_struct *tty, struct file *filp)
 
 static int con_init_done = 0;
 
-static struct tty_operations console_ops = {
+static const struct tty_operations console_ops = {
        .open                   = con_open,
        .close                  = line_close,
        .write                  = line_write,
index 9f70edf5d8ef027c645de108ef9cd901f0f8cd27..11de3ac1eb5c787512b4c1a71f6ac1a16cd6725b 100644 (file)
@@ -18,7 +18,7 @@ struct tty_chan {
        struct termios tt;
 };
 
-static void *tty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *tty_chan_init(char *str, int device, const struct chan_opts *opts)
 {
        struct tty_chan *data;
 
@@ -62,7 +62,7 @@ static int tty_open(int input, int output, int primary, void *d,
        return fd;
 }
 
-struct chan_ops tty_ops = {
+const struct chan_ops tty_ops = {
        .type           = "tty",
        .init           = tty_chan_init,
        .open           = tty_open,
index aaa63666104333f487d01521bb6792250cb40a14..386f8b952982e4317f5254e4016a2e7ba18597d1 100644 (file)
@@ -31,7 +31,7 @@ struct xterm_chan {
 };
 
 /* Not static because it's called directly by the tt mode gdb code */
-void *xterm_init(char *str, int device, struct chan_opts *opts)
+void *xterm_init(char *str, int device, const struct chan_opts *opts)
 {
        struct xterm_chan *data;
 
@@ -194,7 +194,7 @@ static void xterm_free(void *d)
        free(d);
 }
 
-struct chan_ops xterm_ops = {
+const struct chan_ops xterm_ops = {
        .type           = "xterm",
        .init           = xterm_init,
        .open           = xterm_open,
index 1bb5e9d94270493959ef0ffa7053a8cc6d6ce300..572d286ed2c666e21faa970fd2a88f5658056c9a 100644 (file)
@@ -23,21 +23,21 @@ struct chan {
        unsigned int opened:1;
        unsigned int enabled:1;
        int fd;
-       struct chan_ops *ops;
+       const struct chan_ops *ops;
        void *data;
 };
 
 extern void chan_interrupt(struct list_head *chans, struct work_struct *task,
                           struct tty_struct *tty, int irq);
 extern int parse_chan_pair(char *str, struct line *line, int device,
-                          struct chan_opts *opts);
+                          const struct chan_opts *opts);
 extern int open_chan(struct list_head *chans);
 extern int write_chan(struct list_head *chans, const char *buf, int len,
                             int write_irq);
 extern int console_write_chan(struct list_head *chans, const char *buf, 
                              int len);
 extern int console_open_chan(struct line *line, struct console *co,
-                            struct chan_opts *opts);
+                            const struct chan_opts *opts);
 extern void deactivate_chan(struct list_head *chans, int irq);
 extern void reactivate_chan(struct list_head *chans, int irq);
 extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty);
index 659bb3cac32f51f3e7f8017bd137270e068cabf6..a795547a1dbdb5217563457761bd0f13c2a557e4 100644 (file)
@@ -20,7 +20,7 @@ enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
 
 struct chan_ops {
        char *type;
-       void *(*init)(char *, int, struct chan_opts *);
+       void *(*init)(char *, int, const struct chan_opts *);
        int (*open)(int, int, int, void *, char **);
        void (*close)(int, void *);
        int (*read)(int, char *, void *);
@@ -31,8 +31,8 @@ struct chan_ops {
        int winch;
 };
 
-extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops,
-       xterm_ops;
+extern const struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops,
+       tty_ops, xterm_ops;
 
 extern void generic_close(int fd, void *unused);
 extern int generic_read(int fd, char *c_out, void *unused);
index 89e1dc835a5bf0281a7fd38b156d7b4ffe72789d..59cfa9e0cad034739c3add89720269c01f0177c2 100644 (file)
@@ -21,7 +21,7 @@ struct kern_handlers {
        kern_hndl timer_handler;
 };
 
-extern struct kern_handlers handlinfo_kern;
+extern const struct kern_handlers handlinfo_kern;
 
 extern int ncpus;
 extern char *linux_prog;
index 27bf2f6fbc05a60d398cb9b2b8ef0a51605711b2..642c9a0320f9a111af988a8dead98a08ef107efb 100644 (file)
@@ -52,7 +52,7 @@ struct line {
 
        int sigio;
        struct work_struct task;
-       struct line_driver *driver;
+       const struct line_driver *driver;
        int have_irq;
 };
 
@@ -99,7 +99,7 @@ extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts);
 extern void close_lines(struct line *lines, int nlines);
 
 extern int line_config(struct line *lines, unsigned int sizeof_lines,
-                      char *str, struct chan_opts *opts);
+                      char *str, const struct chan_opts *opts);
 extern int line_id(char **str, int *start_out, int *end_out);
 extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
 extern int line_get_config(char *dev, struct line *lines,
index f7de6df60dd717f1ba2a16fc563ecee853a5fe7a..769fba43ee039a2bfb93fd33d32f23a49ba623cd 100644 (file)
@@ -54,8 +54,8 @@ struct transport {
        struct list_head list;
        char *name;
        int (*setup)(char *, char **, void *);
-       struct net_user_info *user;
-       struct net_kern_info *kern;
+       const struct net_user_info *user;
+       const struct net_kern_info *kern;
        int private_size;
        int setup_size;
 };
index 24fb6d8680e11d0f4c44037b7766fce5d7bd7707..120ca21a513a03853a38abf2004a35a1d0b4b173 100644 (file)
@@ -14,6 +14,7 @@
 #include "skas/mm_id.h"
 #include "irq_user.h"
 #include "sysdep/tls.h"
+#include "sysdep/archsetjmp.h"
 
 #define OS_TYPE_FILE 1
 #define OS_TYPE_DIR 2
@@ -198,7 +199,9 @@ extern long os_ptrace_ldt(long pid, long addr, long data);
 extern int os_getpid(void);
 extern int os_getpgrp(void);
 
+#ifdef UML_CONFIG_MODE_TT
 extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
+#endif
 extern void init_new_thread_signals(void);
 extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
 
@@ -216,7 +219,6 @@ extern void os_flush_stdout(void);
  */
 extern void forward_ipi(int fd, int pid);
 extern void kill_child_dead(int pid);
-extern void stop(void);
 extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
 extern int protect_memory(unsigned long addr, unsigned long len,
                          int r, int w, int x, int must_succeed);
@@ -307,12 +309,9 @@ extern int copy_context_skas0(unsigned long stack, int pid);
 extern void userspace(union uml_pt_regs *regs);
 extern void map_stub_pages(int fd, unsigned long code,
                           unsigned long data, unsigned long stack);
-extern void new_thread(void *stack, void **switch_buf_ptr,
-                        void **fork_buf_ptr, void (*handler)(int));
-extern void thread_wait(void *sw, void *fb);
-extern void switch_threads(void *me, void *next);
-extern int start_idle_thread(void *stack, void *switch_buf_ptr,
-                            void **fork_buf_ptr);
+extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
+extern void switch_threads(jmp_buf *me, jmp_buf *you);
+extern int start_idle_thread(void *stack, jmp_buf *switch_buf);
 extern void initial_thread_cb_skas(void (*proc)(void *),
                                 void *arg);
 extern void halt_skas(void);
index 853b26f148c5bde6043a40dd74c288c7a8e6a4f7..e88926b16072e21d0b1c4af2f854397c24a8bfd0 100644 (file)
@@ -14,8 +14,7 @@ extern int proc_mm, ptrace_faultinfo, ptrace_ldt;
 extern int skas_needs_stub;
 
 extern int user_thread(unsigned long stack, int flags);
-extern void new_thread_proc(void *stack, void (*handler)(int sig));
-extern void new_thread_handler(int sig);
+extern void new_thread_handler(void);
 extern void handle_syscall(union uml_pt_regs *regs);
 extern int new_mm(unsigned long stack);
 extern void get_skas_faultinfo(int pid, struct faultinfo * fi);
index ea1ba3d42aee7b87fdf8734a4251534311ff97cd..11bafab669e942b517e403b13cb966eb2c9242b0 100644 (file)
@@ -16,4 +16,7 @@ struct __jmp_buf {
 
 typedef struct __jmp_buf jmp_buf[1];
 
+#define JB_IP __eip
+#define JB_SP __esp
+
 #endif                         /* _SETJMP_H */
index 454fc60aff6d5a0ba12f403bf2b896f67e999aaa..9a5e1a6ec80042095b5f3562d2c2107e85431508 100644 (file)
@@ -18,4 +18,7 @@ struct __jmp_buf {
 
 typedef struct __jmp_buf jmp_buf[1];
 
+#define JB_IP __rip
+#define JB_SP __rsp
+
 #endif                         /* _SETJMP_H */
index 8d353f0feec1bd66286908008f4674a5635cb569..617bb9efc93424ef59fb413cf0394f7266ad12d1 100644 (file)
 #define HOST_FS 25
 #define HOST_GS 26
 
+/* Also defined in asm/ptrace-x86_64.h, but not in libc headers.  So, these
+ * are already defined for kernel code, but not for userspace code.
+ */
+#ifndef FS_BASE
+/* These aren't defined in ptrace.h, but exist in struct user_regs_struct,
+ * which is what x86_64 ptrace actually uses.
+ */
+#define FS_BASE (HOST_FS_BASE * sizeof(long))
+#define GS_BASE (HOST_GS_BASE * sizeof(long))
+#define DS (HOST_DS * sizeof(long))
+#define ES (HOST_ES * sizeof(long))
+#define FS (HOST_FS * sizeof(long))
+#define GS (HOST_GS * sizeof(long))
+#endif
+
 #define REGS_FS_BASE(r) ((r)[HOST_FS_BASE])
 #define REGS_GS_BASE(r) ((r)[HOST_GS_BASE])
 #define REGS_DS(r) ((r)[HOST_DS])
@@ -89,9 +104,12 @@ union uml_pt_regs {
 #endif
 #ifdef UML_CONFIG_MODE_SKAS
        struct skas_regs {
-               /* XXX */
-               unsigned long regs[27];
-               unsigned long fp[65];
+               /* x86_64 ptrace uses sizeof(user_regs_struct) as its register
+                * file size, while i386 uses FRAME_SIZE.  Therefore, we need
+                * to use UM_FRAME_SIZE here instead of HOST_FRAME_SIZE.
+                */
+               unsigned long regs[UM_FRAME_SIZE];
+               unsigned long fp[HOST_FP_SIZE];
                 struct faultinfo faultinfo;
                long syscall;
                int is_user;
@@ -120,11 +138,16 @@ extern int mode_tt;
 #define UPT_R14(r) __CHOOSE_MODE(SC_R14(UPT_SC(r)), REGS_R14((r)->skas.regs))
 #define UPT_R15(r) __CHOOSE_MODE(SC_R15(UPT_SC(r)), REGS_R15((r)->skas.regs))
 #define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
+#define UPT_FS_BASE(r) \
+       __CHOOSE_MODE(SC_FS_BASE(UPT_SC(r)), REGS_FS_BASE((r)->skas.regs))
 #define UPT_FS(r) __CHOOSE_MODE(SC_FS(UPT_SC(r)), REGS_FS((r)->skas.regs))
+#define UPT_GS_BASE(r) \
+       __CHOOSE_MODE(SC_GS_BASE(UPT_SC(r)), REGS_GS_BASE((r)->skas.regs))
 #define UPT_GS(r) __CHOOSE_MODE(SC_GS(UPT_SC(r)), REGS_GS((r)->skas.regs))
 #define UPT_DS(r) __CHOOSE_MODE(SC_DS(UPT_SC(r)), REGS_DS((r)->skas.regs))
 #define UPT_ES(r) __CHOOSE_MODE(SC_ES(UPT_SC(r)), REGS_ES((r)->skas.regs))
 #define UPT_CS(r) __CHOOSE_MODE(SC_CS(UPT_SC(r)), REGS_CS((r)->skas.regs))
+#define UPT_SS(r) __CHOOSE_MODE(SC_SS(UPT_SC(r)), REGS_SS((r)->skas.regs))
 #define UPT_ORIG_RAX(r) \
        __CHOOSE_MODE((r)->tt.orig_rax, REGS_ORIG_RAX((r)->skas.regs))
 
@@ -183,6 +206,13 @@ struct syscall_args {
                 case RBP: val = UPT_RBP(regs); break; \
                 case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \
                 case CS: val = UPT_CS(regs); break; \
+                case SS: val = UPT_SS(regs); break; \
+               case FS_BASE: val = UPT_FS_BASE(regs); break; \
+                case GS_BASE: val = UPT_GS_BASE(regs); break; \
+                case DS: val = UPT_DS(regs); break; \
+                case ES: val = UPT_ES(regs); break; \
+                case FS : val = UPT_FS (regs); break; \
+               case GS: val = UPT_GS(regs); break;         \
                 case EFLAGS: val = UPT_EFLAGS(regs); break; \
                 default :  \
                         panic("Bad register in UPT_REG : %d\n", reg);  \
@@ -214,6 +244,13 @@ struct syscall_args {
                 case RBP: UPT_RBP(regs) = __upt_val; break; \
                 case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
                 case CS: UPT_CS(regs) = __upt_val; break; \
+                case SS: UPT_SS(regs) = __upt_val; break; \
+                case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \
+                case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \
+                case DS: UPT_DS(regs) = __upt_val; break; \
+                case ES: UPT_ES(regs) = __upt_val; break; \
+                case FS: UPT_FS(regs) = __upt_val; break; \
+                case GS: UPT_GS(regs) = __upt_val; break; \
                 case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
                 default :  \
                         panic("Bad register in UPT_SET : %d\n", reg);  \
index a160d9fcc59621b2bc04593df8059f9133a89576..8aee45b074344d979d799330022be9900503764e 100644 (file)
 #define SC_GS(sc) SC_OFFSET(sc, SC_GS)
 #define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS)
 #define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK)
+#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
 #if 0
 #define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX)
 #define SC_DS(sc) SC_OFFSET(sc, SC_DS)
 #define SC_ES(sc) SC_OFFSET(sc, SC_ES)
-#define SC_SS(sc) SC_OFFSET(sc, SC_SS)
 #endif
 
 #endif
index a2d93065b2d0aa10e2b2b363b74366d60276696c..6fa63a2a89e3855df6d351229cdca896c6c3a8f7 100644 (file)
@@ -7,7 +7,7 @@ extra-y := vmlinux.lds
 clean-files :=
 
 obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
-       physmem.o process_kern.o ptrace.o reboot.o resource.o sigio.o \
+       physmem.o process.o ptrace.o reboot.o resource.o sigio.o \
        signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
        um_arch.o umid.o
 
index 2c86e7fdb014356da4029dd767914f8a355fb622..13aa115cd1b4b521d3bdc1259454626f6b3a4a33 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "linux/module.h"
 
-extern void __bb_init_func(void *);
+extern void __bb_init_func(void *)  __attribute__((weak));
 EXPORT_SYMBOL(__bb_init_func);
 
 /* This is defined (and referred to in profiling stub code) only by some GCC
@@ -21,14 +21,3 @@ EXPORT_SYMBOL(__gcov_init);
 
 extern void __gcov_merge_add(void *) __attribute__((weak));
 EXPORT_SYMBOL(__gcov_merge_add);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
index c97045d6d89f5ecf61df62886b54d67bdc42411d..f030e44262ba88a1e7b6b22034f86537ed83c529 100644 (file)
@@ -21,7 +21,6 @@
 #include "mem_user.h"
 #include "os.h"
 
-EXPORT_SYMBOL(stop);
 EXPORT_SYMBOL(uml_physmem);
 EXPORT_SYMBOL(set_signals);
 EXPORT_SYMBOL(get_signals);
@@ -41,12 +40,14 @@ EXPORT_SYMBOL(handle_page_fault);
 EXPORT_SYMBOL(find_iomem);
 
 #ifdef CONFIG_MODE_TT
+EXPORT_SYMBOL(stop);
 EXPORT_SYMBOL(strncpy_from_user_tt);
 EXPORT_SYMBOL(copy_from_user_tt);
 EXPORT_SYMBOL(copy_to_user_tt);
 #endif
 
 #ifdef CONFIG_MODE_SKAS
+EXPORT_SYMBOL(strnlen_user_skas);
 EXPORT_SYMBOL(strncpy_from_user_skas);
 EXPORT_SYMBOL(copy_to_user_skas);
 EXPORT_SYMBOL(copy_from_user_skas);
index 93121c6d26e55594fe8bb505ebdd17ef20de145c..c95855ba6ab576f7063f3bdf825efb8182a13b9a 100644 (file)
@@ -226,7 +226,8 @@ void paging_init(void)
        for(i = 0; i < ARRAY_SIZE(zones_size); i++)
                zones_size[i] = 0;
 
-       zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
+       zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
+               (uml_physmem >> PAGE_SHIFT);
 #ifdef CONFIG_HIGHMEM
        zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT;
 #endif
similarity index 96%
rename from arch/um/kernel/process_kern.c
rename to arch/um/kernel/process.c
index 537895d68ad1ede9b3cd4a5513c565da3dc4b088..fe6c64abda5b029d3f3b1c2a2b891471cf52f3c2 100644 (file)
@@ -1,10 +1,9 @@
-/* 
+/*
  * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
  * Copyright 2003 PathScale, Inc.
  * Licensed under the GPL
  */
 
-#include "linux/config.h"
 #include "linux/kernel.h"
 #include "linux/sched.h"
 #include "linux/interrupt.h"
@@ -113,11 +112,11 @@ void set_current(void *t)
 
 void *_switch_to(void *prev, void *next, void *last)
 {
-        struct task_struct *from = prev;
-        struct task_struct *to= next;
+       struct task_struct *from = prev;
+       struct task_struct *to= next;
 
-        to->thread.prev_sched = from;
-        set_current(to);
+       to->thread.prev_sched = from;
+       set_current(to);
 
        do {
                current->thread.saved_task = NULL ;
@@ -128,7 +127,7 @@ void *_switch_to(void *prev, void *next, void *last)
                prev= current;
        } while(current->thread.saved_task);
 
-        return(current->thread.prev_sched);
+       return(current->thread.prev_sched);
 
 }
 
@@ -142,19 +141,19 @@ void release_thread(struct task_struct *task)
 {
        CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
 }
+
 void exit_thread(void)
 {
        unprotect_stack((unsigned long) current_thread);
 }
+
 void *get_current(void)
 {
        return(current);
 }
 
 int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
-               unsigned long stack_top, struct task_struct * p, 
+               unsigned long stack_top, struct task_struct * p,
                struct pt_regs *regs)
 {
        int ret;
@@ -183,11 +182,11 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
        int save_kmalloc_ok = kmalloc_ok;
 
        kmalloc_ok = 0;
-       CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc, 
+       CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
                         arg);
        kmalloc_ok = save_kmalloc_ok;
 }
+
 unsigned long stack_sp(unsigned long page)
 {
        return(page + PAGE_SIZE - sizeof(void *));
@@ -211,7 +210,7 @@ void default_idle(void)
                 */
                if(need_resched())
                        schedule();
-               
+
                idle_sleep(10);
        }
 }
@@ -226,7 +225,7 @@ int page_size(void)
        return(PAGE_SIZE);
 }
 
-void *um_virt_to_phys(struct task_struct *task, unsigned long addr, 
+void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
                      pte_t *pte_out)
 {
        pgd_t *pgd;
@@ -235,7 +234,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
        pte_t *pte;
        pte_t ptent;
 
-       if(task->mm == NULL) 
+       if(task->mm == NULL)
                return(ERR_PTR(-EINVAL));
        pgd = pgd_offset(task->mm, addr);
        if(!pgd_present(*pgd))
@@ -246,7 +245,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
                return(ERR_PTR(-EINVAL));
 
        pmd = pmd_offset(pud, addr);
-       if(!pmd_present(*pmd)) 
+       if(!pmd_present(*pmd))
                return(ERR_PTR(-EINVAL));
 
        pte = pte_offset_kernel(pmd, addr);
@@ -271,7 +270,7 @@ char *current_cmd(void)
 
 void force_sigbus(void)
 {
-       printk(KERN_ERR "Killing pid %d because of a lack of memory\n", 
+       printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
               current->pid);
        lock_kernel();
        sigaddset(&current->pending.signal, SIGBUS);
index ea3a8e409a6e69c05d18634acc724f7fc5bbcf94..3e3fa7e7e3cfaf6ac5d72d88cc8108faefcdfd6d 100644 (file)
@@ -3,8 +3,7 @@
 # Licensed under the GPL
 #
 
-obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \
-       syscall.o tlb.o uaccess.o
+obj-y := clone.o exec.o mem.o mmu.o process.o syscall.o tlb.o uaccess.o
 
 # clone.o is in the stub, so it can't be built with profiling
 # GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
diff --git a/arch/um/kernel/skas/exec.c b/arch/um/kernel/skas/exec.c
new file mode 100644 (file)
index 0000000..54b7959
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "asm/current.h"
+#include "asm/page.h"
+#include "asm/signal.h"
+#include "asm/ptrace.h"
+#include "asm/uaccess.h"
+#include "asm/mmu_context.h"
+#include "tlb.h"
+#include "skas.h"
+#include "um_mmu.h"
+#include "os.h"
+
+void flush_thread_skas(void)
+{
+       force_flush_all();
+       switch_mm_skas(&current->mm->context.skas.id);
+}
+
+void start_thread_skas(struct pt_regs *regs, unsigned long eip,
+                      unsigned long esp)
+{
+       set_fs(USER_DS);
+       PT_REGS_IP(regs) = eip;
+       PT_REGS_SP(regs) = esp;
+}
diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c
deleted file mode 100644 (file)
index 77ed7bb..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/kernel.h"
-#include "asm/current.h"
-#include "asm/page.h"
-#include "asm/signal.h"
-#include "asm/ptrace.h"
-#include "asm/uaccess.h"
-#include "asm/mmu_context.h"
-#include "tlb.h"
-#include "skas.h"
-#include "um_mmu.h"
-#include "os.h"
-
-void flush_thread_skas(void)
-{
-       force_flush_all();
-        switch_mm_skas(&current->mm->context.skas.id);
-}
-
-void start_thread_skas(struct pt_regs *regs, unsigned long eip, 
-                      unsigned long esp)
-{
-       set_fs(USER_DS);
-        PT_REGS_IP(regs) = eip;
-       PT_REGS_SP(regs) = esp;
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
new file mode 100644 (file)
index 0000000..ae4fa71
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "linux/slab.h"
+#include "linux/ptrace.h"
+#include "linux/proc_fs.h"
+#include "linux/file.h"
+#include "linux/errno.h"
+#include "linux/init.h"
+#include "asm/uaccess.h"
+#include "asm/atomic.h"
+#include "kern_util.h"
+#include "skas.h"
+#include "os.h"
+#include "user_util.h"
+#include "tlb.h"
+#include "kern.h"
+#include "mode.h"
+#include "registers.h"
+
+void switch_to_skas(void *prev, void *next)
+{
+       struct task_struct *from, *to;
+
+       from = prev;
+       to = next;
+
+       /* XXX need to check runqueues[cpu].idle */
+       if(current->pid == 0)
+               switch_timers(0);
+
+       switch_threads(&from->thread.mode.skas.switch_buf,
+                      &to->thread.mode.skas.switch_buf);
+
+       arch_switch_to_skas(current->thread.prev_sched, current);
+
+       if(current->pid == 0)
+               switch_timers(1);
+}
+
+extern void schedule_tail(struct task_struct *prev);
+
+/* This is called magically, by its address being stuffed in a jmp_buf
+ * and being longjmp-d to.
+ */
+void new_thread_handler(void)
+{
+       int (*fn)(void *), n;
+       void *arg;
+
+       if(current->thread.prev_sched != NULL)
+               schedule_tail(current->thread.prev_sched);
+       current->thread.prev_sched = NULL;
+
+       fn = current->thread.request.u.thread.proc;
+       arg = current->thread.request.u.thread.arg;
+
+       /* The return value is 1 if the kernel thread execs a process,
+        * 0 if it just exits
+        */
+       n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
+       if(n == 1){
+               /* Handle any immediate reschedules or signals */
+               interrupt_end();
+               userspace(&current->thread.regs.regs);
+       }
+       else do_exit(0);
+}
+
+void release_thread_skas(struct task_struct *task)
+{
+}
+
+/* Called magically, see new_thread_handler above */
+void fork_handler(void)
+{
+       force_flush_all();
+       if(current->thread.prev_sched == NULL)
+               panic("blech");
+
+       schedule_tail(current->thread.prev_sched);
+
+       /* XXX: if interrupt_end() calls schedule, this call to
+        * arch_switch_to_skas isn't needed. We could want to apply this to
+        * improve performance. -bb */
+       arch_switch_to_skas(current->thread.prev_sched, current);
+
+       current->thread.prev_sched = NULL;
+
+/* Handle any immediate reschedules or signals */
+       interrupt_end();
+
+       userspace(&current->thread.regs.regs);
+}
+
+int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
+                    unsigned long stack_top, struct task_struct * p,
+                    struct pt_regs *regs)
+{
+       void (*handler)(void);
+
+       if(current->thread.forking){
+               memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
+                      sizeof(p->thread.regs.regs.skas));
+               REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
+               if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
+
+               handler = fork_handler;
+
+               arch_copy_thread(&current->thread.arch, &p->thread.arch);
+       }
+       else {
+               init_thread_registers(&p->thread.regs.regs);
+               p->thread.request.u.thread = current->thread.request.u.thread;
+               handler = new_thread_handler;
+       }
+
+       new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
+                  handler);
+       return(0);
+}
+
+int new_mm(unsigned long stack)
+{
+       int fd;
+
+       fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
+       if(fd < 0)
+               return(fd);
+
+       if(skas_needs_stub)
+               map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
+
+       return(fd);
+}
+
+void init_idle_skas(void)
+{
+       cpu_tasks[current_thread->cpu].pid = os_getpid();
+       default_idle();
+}
+
+extern void start_kernel(void);
+
+static int start_kernel_proc(void *unused)
+{
+       int pid;
+
+       block_signals();
+       pid = os_getpid();
+
+       cpu_tasks[0].pid = pid;
+       cpu_tasks[0].task = current;
+#ifdef CONFIG_SMP
+       cpu_online_map = cpumask_of_cpu(0);
+#endif
+       start_kernel();
+       return(0);
+}
+
+extern int userspace_pid[];
+
+int start_uml_skas(void)
+{
+       if(proc_mm)
+               userspace_pid[0] = start_userspace(0);
+
+       init_new_thread_signals();
+
+       init_task.thread.request.u.thread.proc = start_kernel_proc;
+       init_task.thread.request.u.thread.arg = NULL;
+       return(start_idle_thread(task_stack_page(&init_task),
+                                &init_task.thread.mode.skas.switch_buf));
+}
+
+int external_pid_skas(struct task_struct *task)
+{
+#warning Need to look up userspace_pid by cpu
+       return(userspace_pid[0]);
+}
+
+int thread_pid_skas(struct task_struct *task)
+{
+#warning Need to look up userspace_pid by cpu
+       return(userspace_pid[0]);
+}
+
+void kill_off_processes_skas(void)
+{
+       if(proc_mm)
+#warning need to loop over userspace_pids in kill_off_processes_skas
+               os_kill_ptraced_process(userspace_pid[0], 1);
+       else {
+               struct task_struct *p;
+               int pid, me;
+
+               me = os_getpid();
+               for_each_process(p){
+                       if(p->mm == NULL)
+                               continue;
+
+                       pid = p->mm->context.skas.id.u.pid;
+                       os_kill_ptraced_process(pid, 1);
+               }
+       }
+}
+
+unsigned long current_stub_stack(void)
+{
+       if(current->mm == NULL)
+               return(0);
+
+       return(current->mm->context.skas.id.stack);
+}
index 55caeec8b25725d856db3af7a00d678277a520e5..0f3d5d084dc7f21e002ab335eff38f80f95357ce 100644 (file)
 /*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright 2003 PathScale, Inc.
  * Licensed under the GPL
  */
 
+#include "linux/config.h"
+#include "linux/kernel.h"
 #include "linux/sched.h"
+#include "linux/interrupt.h"
+#include "linux/string.h"
+#include "linux/mm.h"
 #include "linux/slab.h"
-#include "linux/ptrace.h"
-#include "linux/proc_fs.h"
-#include "linux/file.h"
-#include "linux/errno.h"
+#include "linux/utsname.h"
+#include "linux/fs.h"
+#include "linux/utime.h"
+#include "linux/smp_lock.h"
+#include "linux/module.h"
 #include "linux/init.h"
+#include "linux/capability.h"
+#include "linux/vmalloc.h"
+#include "linux/spinlock.h"
+#include "linux/proc_fs.h"
+#include "linux/ptrace.h"
+#include "linux/random.h"
+#include "linux/personality.h"
+#include "asm/unistd.h"
+#include "asm/mman.h"
+#include "asm/segment.h"
+#include "asm/stat.h"
+#include "asm/pgtable.h"
+#include "asm/processor.h"
+#include "asm/tlbflush.h"
 #include "asm/uaccess.h"
-#include "asm/atomic.h"
-#include "kern_util.h"
-#include "skas.h"
-#include "os.h"
+#include "asm/user.h"
 #include "user_util.h"
-#include "tlb.h"
+#include "kern_util.h"
 #include "kern.h"
+#include "signal_kern.h"
+#include "init.h"
+#include "irq_user.h"
+#include "mem_user.h"
+#include "tlb.h"
+#include "frame_kern.h"
+#include "sigcontext.h"
+#include "os.h"
 #include "mode.h"
-#include "registers.h"
+#include "mode_kern.h"
+#include "choose-mode.h"
+
+/* This is a per-cpu array.  A processor only modifies its entry and it only
+ * cares about its entry, so it's OK if another processor is modifying its
+ * entry.
+ */
+struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
+
+int external_pid(void *t)
+{
+       struct task_struct *task = t ? t : current;
+
+       return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
+}
+
+int pid_to_processor_id(int pid)
+{
+       int i;
+
+       for(i = 0; i < ncpus; i++){
+               if(cpu_tasks[i].pid == pid) return(i);
+       }
+       return(-1);
+}
+
+void free_stack(unsigned long stack, int order)
+{
+       free_pages(stack, order);
+}
+
+unsigned long alloc_stack(int order, int atomic)
+{
+       unsigned long page;
+       gfp_t flags = GFP_KERNEL;
+
+       if (atomic)
+               flags = GFP_ATOMIC;
+       page = __get_free_pages(flags, order);
+       if(page == 0)
+               return(0);
+       stack_protections(page);
+       return(page);
+}
+
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+       int pid;
+
+       current->thread.request.u.thread.proc = fn;
+       current->thread.request.u.thread.arg = arg;
+       pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
+                     &current->thread.regs, 0, NULL, NULL);
+       if(pid < 0)
+               panic("do_fork failed in kernel_thread, errno = %d", pid);
+       return(pid);
+}
 
-void switch_to_skas(void *prev, void *next)
+void set_current(void *t)
 {
-       struct task_struct *from, *to;
+       struct task_struct *task = t;
 
-       from = prev;
-       to = next;
+       cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
+               { external_pid(task), task });
+}
 
-       /* XXX need to check runqueues[cpu].idle */
-       if(current->pid == 0)
-               switch_timers(0);
+void *_switch_to(void *prev, void *next, void *last)
+{
+        struct task_struct *from = prev;
+        struct task_struct *to= next;
 
-       switch_threads(&from->thread.mode.skas.switch_buf,
-                      to->thread.mode.skas.switch_buf);
+        to->thread.prev_sched = from;
+        set_current(to);
 
-       arch_switch_to_skas(current->thread.prev_sched, current);
+       do {
+               current->thread.saved_task = NULL ;
+               CHOOSE_MODE_PROC(switch_to_tt, switch_to_skas, prev, next);
+               if(current->thread.saved_task)
+                       show_regs(&(current->thread.regs));
+               next= current->thread.saved_task;
+               prev= current;
+       } while(current->thread.saved_task);
+
+        return(current->thread.prev_sched);
 
-       if(current->pid == 0)
-               switch_timers(1);
 }
 
-extern void schedule_tail(struct task_struct *prev);
+void interrupt_end(void)
+{
+       if(need_resched()) schedule();
+       if(test_tsk_thread_flag(current, TIF_SIGPENDING)) do_signal();
+}
 
-void new_thread_handler(int sig)
+void release_thread(struct task_struct *task)
 {
-       int (*fn)(void *), n;
-       void *arg;
+       CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
+}
 
-       fn = current->thread.request.u.thread.proc;
-       arg = current->thread.request.u.thread.arg;
-       os_usr1_signal(1);
-       thread_wait(&current->thread.mode.skas.switch_buf,
-                   current->thread.mode.skas.fork_buf);
+void exit_thread(void)
+{
+       unprotect_stack((unsigned long) current_thread);
+}
 
-       if(current->thread.prev_sched != NULL)
-               schedule_tail(current->thread.prev_sched);
-       current->thread.prev_sched = NULL;
+void *get_current(void)
+{
+       return(current);
+}
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+               unsigned long stack_top, struct task_struct * p,
+               struct pt_regs *regs)
+{
+       int ret;
 
-       /* The return value is 1 if the kernel thread execs a process,
-        * 0 if it just exits
+       p->thread = (struct thread_struct) INIT_THREAD;
+       ret = CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
+                               clone_flags, sp, stack_top, p, regs);
+
+       if (ret || !current->thread.forking)
+               goto out;
+
+       clear_flushed_tls(p);
+
+       /*
+        * Set a new TLS for the child thread?
         */
-       n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
-       if(n == 1){
-               /* Handle any immediate reschedules or signals */
-               interrupt_end();
-               userspace(&current->thread.regs.regs);
+       if (clone_flags & CLONE_SETTLS)
+               ret = arch_copy_tls(p);
+
+out:
+       return ret;
+}
+
+void initial_thread_cb(void (*proc)(void *), void *arg)
+{
+       int save_kmalloc_ok = kmalloc_ok;
+
+       kmalloc_ok = 0;
+       CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
+                        arg);
+       kmalloc_ok = save_kmalloc_ok;
+}
+
+unsigned long stack_sp(unsigned long page)
+{
+       return(page + PAGE_SIZE - sizeof(void *));
+}
+
+int current_pid(void)
+{
+       return(current->pid);
+}
+
+void default_idle(void)
+{
+       CHOOSE_MODE(uml_idle_timer(), (void) 0);
+
+       while(1){
+               /* endless idle loop with no priority at all */
+
+               /*
+                * although we are an idle CPU, we do not want to
+                * get into the scheduler unnecessarily.
+                */
+               if(need_resched())
+                       schedule();
+
+               idle_sleep(10);
        }
-       else do_exit(0);
 }
 
-void new_thread_proc(void *stack, void (*handler)(int sig))
+void cpu_idle(void)
 {
-       init_new_thread_stack(stack, handler);
-       os_usr1_process(os_getpid());
+       CHOOSE_MODE(init_idle_tt(), init_idle_skas());
 }
 
-void release_thread_skas(struct task_struct *task)
+int page_size(void)
 {
+       return(PAGE_SIZE);
 }
 
-void fork_handler(int sig)
+void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
+                     pte_t *pte_out)
 {
-       os_usr1_signal(1);
-       thread_wait(&current->thread.mode.skas.switch_buf,
-                   current->thread.mode.skas.fork_buf);
-       
-       force_flush_all();
-       if(current->thread.prev_sched == NULL)
-               panic("blech");
+       pgd_t *pgd;
+       pud_t *pud;
+       pmd_t *pmd;
+       pte_t *pte;
+       pte_t ptent;
+
+       if(task->mm == NULL)
+               return(ERR_PTR(-EINVAL));
+       pgd = pgd_offset(task->mm, addr);
+       if(!pgd_present(*pgd))
+               return(ERR_PTR(-EINVAL));
+
+       pud = pud_offset(pgd, addr);
+       if(!pud_present(*pud))
+               return(ERR_PTR(-EINVAL));
+
+       pmd = pmd_offset(pud, addr);
+       if(!pmd_present(*pmd))
+               return(ERR_PTR(-EINVAL));
+
+       pte = pte_offset_kernel(pmd, addr);
+       ptent = *pte;
+       if(!pte_present(ptent))
+               return(ERR_PTR(-EINVAL));
+
+       if(pte_out != NULL)
+               *pte_out = ptent;
+       return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK));
+}
 
-       schedule_tail(current->thread.prev_sched);
+char *current_cmd(void)
+{
+#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
+       return("(Unknown)");
+#else
+       void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
+       return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
+#endif
+}
 
-       /* XXX: if interrupt_end() calls schedule, this call to
-        * arch_switch_to_skas isn't needed. We could want to apply this to
-        * improve performance. -bb */
-       arch_switch_to_skas(current->thread.prev_sched, current);
+void force_sigbus(void)
+{
+       printk(KERN_ERR "Killing pid %d because of a lack of memory\n",
+              current->pid);
+       lock_kernel();
+       sigaddset(&current->pending.signal, SIGBUS);
+       recalc_sigpending();
+       current->flags |= PF_SIGNALED;
+       do_exit(SIGBUS | 0x80);
+}
 
-       current->thread.prev_sched = NULL;
+void dump_thread(struct pt_regs *regs, struct user *u)
+{
+}
 
-/* Handle any immediate reschedules or signals */
-       interrupt_end();
+void enable_hlt(void)
+{
+       panic("enable_hlt");
+}
+
+EXPORT_SYMBOL(enable_hlt);
 
-       userspace(&current->thread.regs.regs);
+void disable_hlt(void)
+{
+       panic("disable_hlt");
 }
 
-int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
-                    unsigned long stack_top, struct task_struct * p,
-                    struct pt_regs *regs)
+EXPORT_SYMBOL(disable_hlt);
+
+void *um_kmalloc(int size)
 {
-       void (*handler)(int);
+       return kmalloc(size, GFP_KERNEL);
+}
 
-       if(current->thread.forking){
-               memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
-                      sizeof(p->thread.regs.regs.skas));
-               REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
-               if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
+void *um_kmalloc_atomic(int size)
+{
+       return kmalloc(size, GFP_ATOMIC);
+}
 
-               handler = fork_handler;
+void *um_vmalloc(int size)
+{
+       return vmalloc(size);
+}
 
-               arch_copy_thread(&current->thread.arch, &p->thread.arch);
-       }
-       else {
-               init_thread_registers(&p->thread.regs.regs);
-                p->thread.request.u.thread = current->thread.request.u.thread;
-               handler = new_thread_handler;
-       }
+void *um_vmalloc_atomic(int size)
+{
+       return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL);
+}
 
-       new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
-                  &p->thread.mode.skas.fork_buf, handler);
-       return(0);
+int __cant_sleep(void) {
+       return in_atomic() || irqs_disabled() || in_interrupt();
+       /* Is in_interrupt() really needed? */
+}
+
+unsigned long get_fault_addr(void)
+{
+       return((unsigned long) current->thread.fault_addr);
 }
 
-int new_mm(unsigned long stack)
+EXPORT_SYMBOL(get_fault_addr);
+
+void not_implemented(void)
 {
-       int fd;
+       printk(KERN_DEBUG "Something isn't implemented in here\n");
+}
 
-       fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
-       if(fd < 0)
-               return(fd);
+EXPORT_SYMBOL(not_implemented);
 
-       if(skas_needs_stub)
-               map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
+int user_context(unsigned long sp)
+{
+       unsigned long stack;
 
-       return(fd);
+       stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
+       return(stack != (unsigned long) current_thread);
 }
 
-void init_idle_skas(void)
+extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
+
+void do_uml_exitcalls(void)
 {
-       cpu_tasks[current_thread->cpu].pid = os_getpid();
-       default_idle();
+       exitcall_t *call;
+
+       call = &__uml_exitcall_end;
+       while (--call >= &__uml_exitcall_begin)
+               (*call)();
 }
 
-extern void start_kernel(void);
+char *uml_strdup(char *string)
+{
+       return kstrdup(string, GFP_KERNEL);
+}
 
-static int start_kernel_proc(void *unused)
+int copy_to_user_proc(void __user *to, void *from, int size)
 {
-       int pid;
+       return(copy_to_user(to, from, size));
+}
+
+int copy_from_user_proc(void *to, void __user *from, int size)
+{
+       return(copy_from_user(to, from, size));
+}
+
+int clear_user_proc(void __user *buf, int size)
+{
+       return(clear_user(buf, size));
+}
 
-       block_signals();
-       pid = os_getpid();
+int strlen_user_proc(char __user *str)
+{
+       return(strlen_user(str));
+}
 
-       cpu_tasks[0].pid = pid;
-       cpu_tasks[0].task = current;
+int smp_sigio_handler(void)
+{
 #ifdef CONFIG_SMP
-       cpu_online_map = cpumask_of_cpu(0);
+       int cpu = current_thread->cpu;
+       IPI_handler(cpu);
+       if(cpu != 0)
+               return(1);
 #endif
-       start_kernel();
        return(0);
 }
 
-extern int userspace_pid[];
-
-int start_uml_skas(void)
+int cpu(void)
 {
-       if(proc_mm)
-               userspace_pid[0] = start_userspace(0);
+       return(current_thread->cpu);
+}
+
+static atomic_t using_sysemu = ATOMIC_INIT(0);
+int sysemu_supported;
 
-       init_new_thread_signals();
+void set_using_sysemu(int value)
+{
+       if (value > sysemu_supported)
+               return;
+       atomic_set(&using_sysemu, value);
+}
 
-       init_task.thread.request.u.thread.proc = start_kernel_proc;
-       init_task.thread.request.u.thread.arg = NULL;
-       return(start_idle_thread(task_stack_page(&init_task),
-                                &init_task.thread.mode.skas.switch_buf,
-                                &init_task.thread.mode.skas.fork_buf));
+int get_using_sysemu(void)
+{
+       return atomic_read(&using_sysemu);
 }
 
-int external_pid_skas(struct task_struct *task)
+static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
 {
-#warning Need to look up userspace_pid by cpu
-       return(userspace_pid[0]);
+       if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
+               *eof = 1;
+
+       return strlen(buf);
 }
 
-int thread_pid_skas(struct task_struct *task)
+static int proc_write_sysemu(struct file *file,const char __user *buf, unsigned long count,void *data)
 {
-#warning Need to look up userspace_pid by cpu
-       return(userspace_pid[0]);
+       char tmp[2];
+
+       if (copy_from_user(tmp, buf, 1))
+               return -EFAULT;
+
+       if (tmp[0] >= '0' && tmp[0] <= '2')
+               set_using_sysemu(tmp[0] - '0');
+       return count; /*We use the first char, but pretend to write everything*/
 }
 
-void kill_off_processes_skas(void)
+int __init make_proc_sysemu(void)
 {
-       if(proc_mm)
-#warning need to loop over userspace_pids in kill_off_processes_skas
-               os_kill_ptraced_process(userspace_pid[0], 1);
-       else {
-               struct task_struct *p;
-               int pid, me;
+       struct proc_dir_entry *ent;
+       if (!sysemu_supported)
+               return 0;
 
-               me = os_getpid();
-               for_each_process(p){
-                       if(p->mm == NULL)
-                               continue;
+       ent = create_proc_entry("sysemu", 0600, &proc_root);
 
-                       pid = p->mm->context.skas.id.u.pid;
-                       os_kill_ptraced_process(pid, 1);
-               }
+       if (ent == NULL)
+       {
+               printk(KERN_WARNING "Failed to register /proc/sysemu\n");
+               return(0);
        }
+
+       ent->read_proc  = proc_read_sysemu;
+       ent->write_proc = proc_write_sysemu;
+
+       return 0;
 }
 
-unsigned long current_stub_stack(void)
+late_initcall(make_proc_sysemu);
+
+int singlestepping(void * t)
 {
-       if(current->mm == NULL)
+       struct task_struct *task = t ? t : current;
+
+       if ( ! (task->ptrace & PT_DTRACE) )
                return(0);
 
-       return(current->mm->context.skas.id.stack);
+       if (task->thread.singlestep_syscall)
+               return(1);
+
+       return 2;
+}
+
+/*
+ * Only x86 and x86_64 have an arch_align_stack().
+ * All other arches have "#define arch_align_stack(x) (x)"
+ * in their asm/system.h
+ * As this is included in UML from asm-um/system-generic.h,
+ * we can use it to behave as the subarch does.
+ */
+#ifndef arch_align_stack
+unsigned long arch_align_stack(unsigned long sp)
+{
+       if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+               sp -= get_random_int() % 8192;
+       return sp & ~0xf;
 }
+#endif
index 2454bbd9555d5287f2859e9baa921a39e007c23d..820affbf3e163cc4b99abc627fac7421786b8d57 100644 (file)
@@ -95,7 +95,7 @@ irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
 
        do_timer(regs);
 
-       nsecs = get_time() + local_offset;
+       nsecs = get_time();
        xtime.tv_sec = nsecs / NSEC_PER_SEC;
        xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC;
 
index e5eeaf2b6af118c33401528a0e03ff206af15ed9..61a23fff4395e822f1ee481a9ab589003201b1ba 100644 (file)
@@ -140,14 +140,6 @@ void segv_handler(int sig, union uml_pt_regs *regs)
        segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs);
 }
 
-struct kern_handlers handlinfo_kern = {
-       .relay_signal = relay_signal,
-       .winch = winch,
-       .bus_handler = relay_signal,
-       .page_fault = segv_handler,
-       .sigio_handler = sigio_handler,
-       .timer_handler = timer_handler
-};
 /*
  * We give a *copy* of the faultinfo in the regs to segv.
  * This must be done, since nesting SEGVs could overwrite
@@ -253,6 +245,15 @@ void winch(int sig, union uml_pt_regs *regs)
        do_IRQ(WINCH_IRQ, regs);
 }
 
+const struct kern_handlers handlinfo_kern = {
+       .relay_signal = relay_signal,
+       .winch = winch,
+       .bus_handler = bus_handler,
+       .page_fault = segv_handler,
+       .sigio_handler = sigio_handler,
+       .timer_handler = timer_handler
+};
+
 void trap_init(void)
 {
 }
index 7896cf98232df1a06c6593957e24597b8dbb7e04..55005710dcbbc8254fc3bbea46f3f3b6ad065ad1 100644 (file)
@@ -106,7 +106,7 @@ static void c_stop(struct seq_file *m, void *v)
 {
 }
 
-struct seq_operations cpuinfo_op = {
+const struct seq_operations cpuinfo_op = {
        .start  = c_start,
        .next   = c_next,
        .stop   = c_stop,
index f4bfc4c7ccac25504c359f805013c35adb3ce78b..b4183929b32cb28e3d6e5f4efaa445676293e86a 100644 (file)
@@ -4,15 +4,19 @@
 #
 
 obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \
-       signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o tls.o \
+       signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \
        user_syms.o util.o drivers/ sys-$(SUBARCH)/
 
 obj-$(CONFIG_MODE_SKAS) += skas/
+
+obj-$(CONFIG_MODE_TT) += tt.o
+user-objs-$(CONFIG_MODE_TT) += tt.o
+
 obj-$(CONFIG_TTY_LOG) += tty_log.o
 user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 
 USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \
-       process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o tls.o \
+       process.o sigio.o signal.o start_up.o time.o trap.o tty.o tls.o \
        uaccess.o umid.o util.o
 
 CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
index b84f6c4740f74efc9389c2e042a0de3198649707..57ecdaf2f67e872f029da7a8b501f970e4950d1b 100644 (file)
@@ -13,7 +13,7 @@ struct ethertap_data {
        void *dev;
 };
 
-extern struct net_user_info ethertap_user_info;
+extern const struct net_user_info ethertap_user_info;
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
index 768606bec233222de64a8698b535a62e4a472157..16385e2ada854ebd1c965364a6d065f709294c3f 100644 (file)
@@ -65,7 +65,7 @@ static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
        return(net_send(fd, (*skb)->data, (*skb)->len));
 }
 
-struct net_kern_info ethertap_kern_info = {
+const struct net_kern_info ethertap_kern_info = {
        .init                   = etap_init,
        .protocol               = eth_protocol,
        .read                   = etap_read,
index 8f49507e64ef5ac0091fe22189bea6413e427469..f559bdf746e6099bfb7593215ded118626a899df 100644 (file)
@@ -216,7 +216,7 @@ static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
        etap_close_addr(addr, netmask, &pri->control_fd);
 }
 
-struct net_user_info ethertap_user_info = {
+const struct net_user_info ethertap_user_info = {
        .init           = etap_user_init,
        .open           = etap_open,
        .close          = etap_close,
index 25d4a2868814bdd83ebd083448d1006a3e1962af..d3e8d3af62454af21338709d5dda4c80996ee62f 100644 (file)
@@ -16,7 +16,7 @@ struct tuntap_data {
        void *dev;
 };
 
-extern struct net_user_info tuntap_user_info;
+extern const struct net_user_info tuntap_user_info;
 
 #endif
 
index 190009a6f89cd2a713f8b6a44fc1b1b12bff6c0e..0edbac63c52708009ac792442fee6eb75dc2fbb5 100644 (file)
@@ -53,7 +53,7 @@ static int tuntap_write(int fd, struct sk_buff **skb,
        return(net_write(fd, (*skb)->data, (*skb)->len));
 }
 
-struct net_kern_info tuntap_kern_info = {
+const struct net_kern_info tuntap_kern_info = {
        .init                   = tuntap_init,
        .protocol               = eth_protocol,
        .read                   = tuntap_read,
index 87c3aa0252db5530190d0ac0837dfe8ec55d3aa6..e846b23f7558582e8bf51f09a18d91b698c25f65 100644 (file)
@@ -205,7 +205,7 @@ static int tuntap_set_mtu(int mtu, void *data)
        return(mtu);
 }
 
-struct net_user_info tuntap_user_info = {
+const struct net_user_info tuntap_user_info = {
        .init           = tuntap_user_init,
        .open           = tuntap_open,
        .close          = tuntap_close,
index 42e3d1ed802cadf01a6f06345daf8ecc327f05d5..cb9ab54146cc6126ac5a6344a520f4e0e8a8f25c 100644 (file)
@@ -444,56 +444,22 @@ void map_stub_pages(int fd, unsigned long code,
        }
 }
 
-void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
-               void (*handler)(int))
+void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
 {
-       unsigned long flags;
-       jmp_buf switch_buf, fork_buf;
-
-       *switch_buf_ptr = &switch_buf;
-       *fork_buf_ptr = &fork_buf;
-
-       /* Somewhat subtle - siglongjmp restores the signal mask before doing
-        * the longjmp.  This means that when jumping from one stack to another
-        * when the target stack has interrupts enabled, an interrupt may occur
-        * on the source stack.  This is bad when starting up a process because
-        * it's not supposed to get timer ticks until it has been scheduled.
-        * So, we disable interrupts around the sigsetjmp to ensure that
-        * they can't happen until we get back here where they are safe.
-        */
-       flags = get_signals();
-       block_signals();
-       if(UML_SETJMP(&fork_buf) == 0)
-               new_thread_proc(stack, handler);
-
-       remove_sigstack();
-
-       set_signals(flags);
+       (*buf)[0].JB_IP = (unsigned long) handler;
+       (*buf)[0].JB_SP = (unsigned long) stack +
+               (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *);
 }
 
 #define INIT_JMP_NEW_THREAD 0
-#define INIT_JMP_REMOVE_SIGSTACK 1
-#define INIT_JMP_CALLBACK 2
-#define INIT_JMP_HALT 3
-#define INIT_JMP_REBOOT 4
-
-void thread_wait(void *sw, void *fb)
-{
-       jmp_buf buf, **switch_buf = sw, *fork_buf;
-
-       *switch_buf = &buf;
-       fork_buf = fb;
-       if(UML_SETJMP(&buf) == 0)
-               UML_LONGJMP(fork_buf, INIT_JMP_REMOVE_SIGSTACK);
-}
+#define INIT_JMP_CALLBACK 1
+#define INIT_JMP_HALT 2
+#define INIT_JMP_REBOOT 3
 
-void switch_threads(void *me, void *next)
+void switch_threads(jmp_buf *me, jmp_buf *you)
 {
-       jmp_buf my_buf, **me_ptr = me, *next_buf = next;
-
-       *me_ptr = &my_buf;
-       if(UML_SETJMP(&my_buf) == 0)
-               UML_LONGJMP(next_buf, 1);
+       if(UML_SETJMP(me) == 0)
+               UML_LONGJMP(you, 1);
 }
 
 static jmp_buf initial_jmpbuf;
@@ -503,23 +469,21 @@ static void (*cb_proc)(void *arg);
 static void *cb_arg;
 static jmp_buf *cb_back;
 
-int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
+int start_idle_thread(void *stack, jmp_buf *switch_buf)
 {
-       jmp_buf **switch_buf = switch_buf_ptr;
        int n;
 
        set_handler(SIGWINCH, (__sighandler_t) sig_handler,
                    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
                    SIGVTALRM, -1);
 
-       *fork_buf_ptr = &initial_jmpbuf;
        n = UML_SETJMP(&initial_jmpbuf);
        switch(n){
        case INIT_JMP_NEW_THREAD:
-               new_thread_proc((void *) stack, new_thread_handler);
-               break;
-       case INIT_JMP_REMOVE_SIGSTACK:
-               remove_sigstack();
+               (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
+               (*switch_buf)[0].JB_SP = (unsigned long) stack +
+                       (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) -
+                       sizeof(void *);
                break;
        case INIT_JMP_CALLBACK:
                (*cb_proc)(cb_arg);
@@ -534,7 +498,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
        default:
                panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
        }
-       UML_LONGJMP(*switch_buf, 1);
+       UML_LONGJMP(switch_buf, 1);
 }
 
 void initial_thread_cb_skas(void (*proc)(void *), void *arg)
index 59cc70275754afebfb030fc73b48ebc4a5ccde8a..0e32adf03be1940a0cace32c2e4842d3eef7a78a 100644 (file)
@@ -4,7 +4,7 @@ obj-y = bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
 
 obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
 
-subarch-obj-y = lib/bitops.o kernel/semaphore.o
+subarch-obj-y = lib/bitops.o lib/semaphore.o
 subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem.o
 subarch-obj-$(CONFIG_MODULES) += kernel/module.o
 
index 581ce9af0ec8f5ed4572e5cf0050b0f7cf90d3a7..32ae1378f35c7ea6dbcb639d5a73b215fa71c93f 100644 (file)
@@ -85,6 +85,9 @@ config ARCH_MAY_HAVE_PC_FDC
        bool
        default y
 
+config ARCH_POPULATES_NODE_MAP
+       def_bool y
+
 config DMI
        bool
        default y
@@ -109,6 +112,7 @@ config X86_PC
 
 config X86_VSMP
        bool "Support for ScaleMP vSMP"
+       depends on PCI
         help
          Support for ScaleMP vSMP systems.  Say 'Y' here if this kernel is
          supposed to run on these EM64T-based machines.  Only choose this option
@@ -167,6 +171,7 @@ config X86_GOOD_APIC
 
 config MICROCODE
        tristate "/dev/cpu/microcode - Intel CPU microcode support"
+       select FW_LOADER
        ---help---
          If you say Y here the 'File systems' section, you will be
          able to update the microcode on Intel processors. You will
@@ -182,6 +187,11 @@ config MICROCODE
          If you use modprobe or kmod you may also want to add the line
          'alias char-major-10-184 microcode' to your /etc/modules.conf file.
 
+config MICROCODE_OLD_INTERFACE
+       bool
+       depends on MICROCODE
+       default y
+
 config X86_MSR
        tristate "/dev/cpu/*/msr - Model-specific register support"
        help
@@ -295,7 +305,7 @@ config NUMA
 
 config K8_NUMA
        bool "Old style AMD Opteron NUMA detection"
-       depends on NUMA
+       depends on NUMA && PCI
        default y
        help
         Enable K8 NUMA node topology detection.  You should say Y here if
@@ -425,7 +435,6 @@ config IOMMU
 
 config CALGARY_IOMMU
        bool "IBM Calgary IOMMU support"
-       default y
        select SWIOTLB
        depends on PCI && EXPERIMENTAL
        help
@@ -472,8 +481,7 @@ config X86_MCE_AMD
           the DRAM Error Threshold.
 
 config KEXEC
-       bool "kexec system call (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       bool "kexec system call"
        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
@@ -492,7 +500,14 @@ config CRASH_DUMP
        bool "kernel crash dumps (EXPERIMENTAL)"
        depends on EXPERIMENTAL
        help
-               Generate crash dump after being started by kexec.
+          Generate crash dump after being started by kexec.
+          This should be normally only set in special crash dump kernels
+          which are loaded in the main kernel with kexec-tools into
+          a specially reserved region and then later executed after
+          a crash by kdump/kexec. The crash dump kernel must be compiled
+         to a memory address not used by the main kernel or BIOS using
+         PHYSICAL_START.
+          For more details see Documentation/kdump/kdump.txt
 
 config PHYSICAL_START
        hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP)
@@ -530,6 +545,30 @@ config SECCOMP
 
          If unsure, say Y. Only embedded should say N here.
 
+config CC_STACKPROTECTOR
+       bool "Enable -fstack-protector buffer overflow detection (EXPRIMENTAL)"
+       depends on EXPERIMENTAL
+       help
+         This option turns on the -fstack-protector GCC feature. This
+         feature puts, at the beginning of critical functions, a canary
+         value on the stack just before the return address, and validates
+         the value just before actually returning.  Stack based buffer
+         overflows (that need to overwrite this return address) now also
+         overwrite the canary, which gets detected and the attack is then
+         neutralized via a kernel panic.
+
+         This feature requires gcc version 4.2 or above, or a distribution
+         gcc with the feature backported. Older versions are automatically
+         detected and for those versions, this configuration option is ignored.
+
+config CC_STACKPROTECTOR_ALL
+       bool "Use stack-protector for all functions"
+       depends on CC_STACKPROTECTOR
+       help
+         Normally, GCC only inserts the canary value protection for
+         functions that use large-ish on-stack buffers. By enabling
+         this option, GCC will be asked to do this for ALL functions.
+
 source kernel/Kconfig.hz
 
 config REORDER
index 431bb4bc36cdc950b1a9168a3abfcb0b954eb373..1c0f18d4f887a574734df7b6302ef8c362b8533d 100644 (file)
@@ -54,6 +54,16 @@ endif
 cflags-y += $(call cc-option,-funit-at-a-time)
 # prevent gcc from generating any FP code by mistake
 cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+# do binutils support CFI?
+cflags-y += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+
+# is .cfi_signal_frame supported too?
+cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
+AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
+
+cflags-$(CONFIG_CC_STACKPROTECTOR) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC) -fstack-protector )
+cflags-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC) -fstack-protector-all )
 
 CFLAGS += $(cflags-y)
 CFLAGS_KERNEL += $(cflags-kernel-y)
index f89d96f11a9fc9c6f7f1cd11c44efbb71cea3a36..e70fa6e1da0800b8a70f4741ba6ee5c05e439453 100644 (file)
@@ -7,7 +7,8 @@
 #
 
 targets                := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
-EXTRA_AFLAGS   := -traditional -m32
+EXTRA_AFLAGS   := -traditional
+AFLAGS         := $(subst -m64,-m32,$(AFLAGS))
 
 # cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with
 # -m32
index a50b631f4d2b017fbb5433726aaf727f4a10883b..c3bfd223ab49e2866bc54f154dac6bf9867e18a9 100644 (file)
@@ -526,12 +526,12 @@ is_disk1:
        movw    %cs, %ax                        # aka SETUPSEG
        subw    $DELTA_INITSEG, %ax             # aka INITSEG
        movw    %ax, %ds
-       movw    $0, (0x1ff)                     # default is no pointing device
+       movb    $0, (0x1ff)                     # default is no pointing device
        int     $0x11                           # int 0x11: equipment list
        testb   $0x04, %al                      # check if mouse installed
        jz      no_psmouse
 
-       movw    $0xAA, (0x1ff)                  # device present
+       movb    $0xAA, (0x1ff)                  # device present
 no_psmouse:
 
 #include "../../i386/boot/edd.S"
index 5fb970715941176250390d7dc4ab0ae5ba079ae5..647610ecb5802b39e5e3e09b9e649381acb6a36d 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.18-rc4
-# Thu Aug 24 21:05:55 2006
+# Linux kernel version: 2.6.18-git5
+# Tue Sep 26 09:30:47 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -19,6 +19,7 @@ CONFIG_GENERIC_ISA_DMA=y
 CONFIG_GENERIC_IOMAP=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 CONFIG_DMI=y
+CONFIG_AUDIT_ARCH=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -38,16 +39,16 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_CPUSETS is not set
 # CONFIG_RELAY is not set
 CONFIG_INITRAMFS_SOURCE=""
-CONFIG_UID16=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_EMBEDDED is not set
+CONFIG_UID16=y
+CONFIG_SYSCTL=y
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
@@ -56,12 +57,12 @@ CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_RT_MUTEXES=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
@@ -160,6 +161,7 @@ CONFIG_X86_MCE_AMD=y
 # CONFIG_CRASH_DUMP is not set
 CONFIG_PHYSICAL_START=0x200000
 CONFIG_SECCOMP=y
+# CONFIG_CC_STACKPROTECTOR is not set
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
 # CONFIG_HZ_1000 is not set
@@ -307,18 +309,23 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_IPV6_ROUTER_PREF is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
 # CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
 # CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
 # CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_SUBTREES is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
@@ -345,7 +352,6 @@ CONFIG_IPV6=y
 # CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 
@@ -487,6 +493,7 @@ CONFIG_IDEDMA_AUTO=y
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_NETLINK=y
 # CONFIG_SCSI_PROC_FS is not set
 
 #
@@ -508,12 +515,13 @@ CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
 #
-# SCSI Transport Attributes
+# SCSI Transports
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
 # CONFIG_SCSI_ISCSI_ATTRS is not set
 CONFIG_SCSI_SAS_ATTRS=y
+# CONFIG_SCSI_SAS_LIBSAS is not set
 
 #
 # SCSI low-level drivers
@@ -532,29 +540,14 @@ CONFIG_AIC79XX_RESET_DELAY_MS=4000
 # CONFIG_AIC79XX_DEBUG_ENABLE is not set
 CONFIG_AIC79XX_DEBUG_MASK=0
 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_ARCMSR is not set
 CONFIG_MEGARAID_NEWGEN=y
 CONFIG_MEGARAID_MM=y
 CONFIG_MEGARAID_MAILBOX=y
 # CONFIG_MEGARAID_LEGACY is not set
 CONFIG_MEGARAID_SAS=y
-CONFIG_SCSI_SATA=y
-CONFIG_SCSI_SATA_AHCI=y
-CONFIG_SCSI_SATA_SVW=y
-CONFIG_SCSI_ATA_PIIX=y
-# CONFIG_SCSI_SATA_MV is not set
-CONFIG_SCSI_SATA_NV=y
-# CONFIG_SCSI_PDC_ADMA is not set
 # CONFIG_SCSI_HPTIOP is not set
-# CONFIG_SCSI_SATA_QSTOR is not set
-# CONFIG_SCSI_SATA_PROMISE is not set
-# CONFIG_SCSI_SATA_SX4 is not set
-CONFIG_SCSI_SATA_SIL=y
-# CONFIG_SCSI_SATA_SIL24 is not set
-# CONFIG_SCSI_SATA_SIS is not set
-# CONFIG_SCSI_SATA_ULI is not set
-CONFIG_SCSI_SATA_VIA=y
-# CONFIG_SCSI_SATA_VITESSE is not set
-CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
@@ -563,6 +556,7 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # 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
@@ -572,6 +566,62 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
 
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+CONFIG_ATA=y
+CONFIG_SATA_AHCI=y
+CONFIG_SATA_SVW=y
+CONFIG_ATA_PIIX=y
+# CONFIG_SATA_MV is not set
+CONFIG_SATA_NV=y
+# 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=y
+# CONFIG_SATA_SIL24 is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_ULI is not set
+CONFIG_SATA_VIA=y
+# CONFIG_SATA_VITESSE is not set
+CONFIG_SATA_INTEL_COMBINED=y
+# 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_JMICRON is not set
+# CONFIG_PATA_LEGACY is not set
+# CONFIG_PATA_TRIFLEX 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_QDI 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
+
 #
 # Multi-device support (RAID and LVM)
 #
@@ -678,6 +728,7 @@ CONFIG_NET_PCI=y
 # CONFIG_ADAPTEC_STARFIRE is not set
 CONFIG_B44=y
 CONFIG_FORCEDETH=y
+# CONFIG_FORCEDETH_NAPI is not set
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 CONFIG_E100=y
@@ -714,6 +765,7 @@ CONFIG_E1000=y
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
 CONFIG_BNX2=y
+# CONFIG_QLA3XXX is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -1036,6 +1088,7 @@ CONFIG_SOUND=y
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=y
+CONFIG_OSS_OBSOLETE_DRIVER=y
 # CONFIG_SOUND_BT878 is not set
 # CONFIG_SOUND_EMU10K1 is not set
 # CONFIG_SOUND_FUSION is not set
@@ -1046,7 +1099,6 @@ CONFIG_SOUND_ICH=y
 # CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_OSS is not set
-# CONFIG_SOUND_TVMIXER is not set
 
 #
 # USB support
@@ -1203,7 +1255,6 @@ CONFIG_USB_MON=y
 # InfiniBand support
 #
 # CONFIG_INFINIBAND is not set
-# CONFIG_IPATH_CORE is not set
 
 #
 # EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
@@ -1448,10 +1499,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y
 #
 # CONFIG_CRYPTO is not set
 
-#
-# Hardware crypto devices
-#
-
 #
 # Library routines
 #
index 3bf58af98936fda96afff0f79b873ea4c61750ed..396d3c10001173745cb08cfe0569101319987fdb 100644 (file)
@@ -333,7 +333,8 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                        return error;
                }
 
-               error = bprm->file->f_op->read(bprm->file, (char *)text_addr,
+               error = bprm->file->f_op->read(bprm->file,
+                        (char __user *)text_addr,
                          ex.a_text+ex.a_data, &pos);
                if ((signed long)error < 0) {
                        send_sig(SIGKILL, current, 0);
@@ -366,7 +367,8 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                        down_write(&current->mm->mmap_sem);
                        do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data);
                        up_write(&current->mm->mmap_sem);
-                       bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex),
+                       bprm->file->f_op->read(bprm->file,
+                                       (char __user *)N_TXTADDR(ex),
                                        ex.a_text+ex.a_data, &pos);
                        flush_icache_range((unsigned long) N_TXTADDR(ex),
                                           (unsigned long) N_TXTADDR(ex) +
@@ -477,7 +479,7 @@ static int load_aout_library(struct file *file)
                do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss);
                up_write(&current->mm->mmap_sem);
                
-               file->f_op->read(file, (char *)start_addr,
+               file->f_op->read(file, (char __user *)start_addr,
                        ex.a_text + ex.a_data, &pos);
                flush_icache_range((unsigned long) start_addr,
                                   (unsigned long) start_addr + ex.a_text + ex.a_data);
index 25e5ca22204c5007c3b523413f59785d49c0a8e3..a6ba9951e86ce3d4f7a40da027b0516ed548486c 100644 (file)
@@ -113,25 +113,19 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 }
 
 asmlinkage long
-sys32_sigsuspend(int history0, int history1, old_sigset_t mask,
-                struct pt_regs *regs)
+sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
-       sigset_t saveset;
-
        mask &= _BLOCKABLE;
        spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
+       current->saved_sigmask = current->blocked;
        siginitset(&current->blocked, mask);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       regs->rax = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(regs, &saveset))
-                       return -EINTR;
-       }
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_thread_flag(TIF_RESTORE_SIGMASK);
+       return -ERESTARTNOHAND;
 }
 
 asmlinkage long
@@ -437,15 +431,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
                goto give_sigsegv;
 
-       {
-               struct exec_domain *ed = current_thread_info()->exec_domain;
-               err |= __put_user((ed
-                          && ed->signal_invmap
-                          && sig < 32
-                          ? ed->signal_invmap[sig]
-                          : sig),
-                         &frame->sig);
-       }
+       err |= __put_user(sig, &frame->sig);
        if (err)
                goto give_sigsegv;
 
@@ -492,6 +478,11 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
        regs->rsp = (unsigned long) frame;
        regs->rip = (unsigned long) ka->sa.sa_handler;
 
+       /* Make -mregparm=3 work */
+       regs->rax = sig;
+       regs->rdx = 0;
+       regs->rcx = 0;
+
        asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); 
        asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); 
 
@@ -499,20 +490,20 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
        regs->ss = __USER32_DS; 
 
        set_fs(USER_DS);
-    regs->eflags &= ~TF_MASK;
-    if (test_thread_flag(TIF_SINGLESTEP))
-        ptrace_notify(SIGTRAP);
+       regs->eflags &= ~TF_MASK;
+       if (test_thread_flag(TIF_SINGLESTEP))
+               ptrace_notify(SIGTRAP);
 
 #if DEBUG_SIG
        printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
                current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
-       return 1;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
-       return 0;
+       return -EFAULT;
 }
 
 int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -595,18 +586,18 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->ss = __USER32_DS; 
 
        set_fs(USER_DS);
-    regs->eflags &= ~TF_MASK;
-    if (test_thread_flag(TIF_SINGLESTEP))
-        ptrace_notify(SIGTRAP);
+       regs->eflags &= ~TF_MASK;
+       if (test_thread_flag(TIF_SINGLESTEP))
+               ptrace_notify(SIGTRAP);
 
 #if DEBUG_SIG
        printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
                current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
-       return 1;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
-       return 0;
+       return -EFAULT;
 }
index 5d4a7d125ed0bbd9cbc0729290b25475b3a1534d..b4aa875e175becbaa59b27f6a1be2554b1f6aca1 100644 (file)
@@ -71,6 +71,7 @@
  */    
 ENTRY(ia32_sysenter_target)
        CFI_STARTPROC32 simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA     rsp,0
        CFI_REGISTER    rsp,rbp
        swapgs
@@ -186,6 +187,7 @@ ENDPROC(ia32_sysenter_target)
  */    
 ENTRY(ia32_cstar_target)
        CFI_STARTPROC32 simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA     rsp,PDA_STACKOFFSET
        CFI_REGISTER    rip,rcx
        /*CFI_REGISTER  rflags,r11*/
@@ -293,6 +295,7 @@ ia32_badarg:
 
 ENTRY(ia32_syscall)
        CFI_STARTPROC   simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA     rsp,SS+8-RIP
        /*CFI_REL_OFFSET        ss,SS-RIP*/
        CFI_REL_OFFSET  rsp,RSP-RIP
@@ -370,6 +373,7 @@ ENTRY(ia32_ptregs_common)
        popq %r11
        CFI_ENDPROC
        CFI_STARTPROC32 simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA     rsp,SS+8-ARGOFFSET
        CFI_REL_OFFSET  rax,RAX-ARGOFFSET
        CFI_REL_OFFSET  rcx,RCX-ARGOFFSET
@@ -703,8 +707,8 @@ ia32_sys_call_table:
        .quad sys_readlinkat            /* 305 */
        .quad sys_fchmodat
        .quad sys_faccessat
-       .quad quiet_ni_syscall          /* pselect6 for now */
-       .quad quiet_ni_syscall          /* ppoll for now */
+       .quad compat_sys_pselect6
+       .quad compat_sys_ppoll
        .quad sys_unshare               /* 310 */
        .quad compat_sys_set_robust_list
        .quad compat_sys_get_robust_list
@@ -713,4 +717,5 @@ ia32_sys_call_table:
        .quad sys_tee
        .quad compat_sys_vmsplice
        .quad compat_sys_move_pages
+       .quad sys_getcpu
 ia32_syscall_end:              
index 659c0722f6b825c75ca7d86743a872630cd9c45f..d18198ed636b59d006bb3b87e68ea0bc50e87ff7 100644 (file)
@@ -117,6 +117,10 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val)
                        if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1)
                               return -EIO;
                child->thread.debugreg7 = val; 
+               if (val)
+                       set_tsk_thread_flag(child, TIF_DEBUG);
+               else
+                       clear_tsk_thread_flag(child, TIF_DEBUG);
                break; 
                    
        default:
@@ -371,8 +375,10 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
                ret = -EIO;
                if (!access_ok(VERIFY_READ, u, sizeof(*u)))
                        break;
-               /* no checking to be bug-to-bug compatible with i386 */
-               __copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u));
+               /* no checking to be bug-to-bug compatible with i386. */
+               /* but silence warning */
+               if (__copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u)))
+                       ;
                set_stopped_child_used_math(child);
                child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
                ret = 0; 
index 9c130993380d8b3a27da7437da33be064f713052..f280d3665f4bed8fa07513078f39113369814354 100644 (file)
@@ -60,6 +60,7 @@
 #include <linux/highuid.h>
 #include <linux/vmalloc.h>
 #include <linux/fsnotify.h>
+#include <linux/sysctl.h>
 #include <asm/mman.h>
 #include <asm/types.h>
 #include <asm/uaccess.h>
@@ -389,7 +390,9 @@ sys32_rt_sigprocmask(int how, compat_sigset_t __user *set,
                }
        }
        set_fs (KERNEL_DS);
-       ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL,
+       ret = sys_rt_sigprocmask(how,
+                                set ? (sigset_t __user *)&s : NULL,
+                                oset ? (sigset_t __user *)&s : NULL,
                                 sigsetsize); 
        set_fs (old_fs);
        if (ret) return ret;
@@ -541,7 +544,7 @@ sys32_sysinfo(struct sysinfo32 __user *info)
        int bitcount = 0;
        
        set_fs (KERNEL_DS);
-       ret = sys_sysinfo(&s);
+       ret = sys_sysinfo((struct sysinfo __user *)&s);
        set_fs (old_fs);
 
         /* Check to see if any memory value is too large for 32-bit and scale
@@ -589,7 +592,7 @@ sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *int
        mm_segment_t old_fs = get_fs ();
        
        set_fs (KERNEL_DS);
-       ret = sys_sched_rr_get_interval(pid, &t);
+       ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
        set_fs (old_fs);
        if (put_compat_timespec(&t, interval))
                return -EFAULT;
@@ -605,7 +608,7 @@ sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize)
        mm_segment_t old_fs = get_fs();
                
        set_fs (KERNEL_DS);
-       ret = sys_rt_sigpending(&s, sigsetsize);
+       ret = sys_rt_sigpending((sigset_t __user *)&s, sigsetsize);
        set_fs (old_fs);
        if (!ret) {
                switch (_NSIG_WORDS) {
@@ -630,7 +633,7 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
        if (copy_siginfo_from_user32(&info, uinfo))
                return -EFAULT;
        set_fs (KERNEL_DS);
-       ret = sys_rt_sigqueueinfo(pid, sig, &info);
+       ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
        set_fs (old_fs);
        return ret;
 }
@@ -645,7 +648,7 @@ sys32_pause(void)
 }
 
 
-#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_SYSCTL_SYSCALL
 struct sysctl_ia32 {
        unsigned int    name;
        int             nlen;
@@ -666,9 +669,6 @@ sys32_sysctl(struct sysctl_ia32 __user *args32)
        size_t oldlen;
        int __user *namep;
        long ret;
-       extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
-                    void *newval, size_t newlen);
-
 
        if (copy_from_user(&a32, args32, sizeof (a32)))
                return -EFAULT;
@@ -692,7 +692,8 @@ sys32_sysctl(struct sysctl_ia32 __user *args32)
 
        set_fs(KERNEL_DS);
        lock_kernel();
-       ret = do_sysctl(namep, a32.nlen, oldvalp, &oldlen, newvalp, (size_t) a32.newlen);
+       ret = do_sysctl(namep, a32.nlen, oldvalp, (size_t __user *)&oldlen,
+                       newvalp, (size_t) a32.newlen);
        unlock_kernel();
        set_fs(old_fs);
 
@@ -743,7 +744,8 @@ sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
                return -EFAULT;
                
        set_fs(KERNEL_DS);
-       ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+       ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL,
+                          count);
        set_fs(old_fs);
        
        if (offset && put_user(of, offset))
@@ -778,7 +780,7 @@ asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len,
 
 asmlinkage long sys32_olduname(struct oldold_utsname __user * name)
 {
-       int error;
+       int err;
 
        if (!name)
                return -EFAULT;
@@ -787,27 +789,31 @@ asmlinkage long sys32_olduname(struct oldold_utsname __user * name)
   
        down_read(&uts_sem);
        
-       error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
-        __put_user(0,name->sysname+__OLD_UTS_LEN);
-        __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
-        __put_user(0,name->nodename+__OLD_UTS_LEN);
-        __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
-        __put_user(0,name->release+__OLD_UTS_LEN);
-        __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
-        __put_user(0,name->version+__OLD_UTS_LEN);
+       err = __copy_to_user(&name->sysname,&system_utsname.sysname,
+                               __OLD_UTS_LEN);
+       err |= __put_user(0,name->sysname+__OLD_UTS_LEN);
+       err |= __copy_to_user(&name->nodename,&system_utsname.nodename,
+                               __OLD_UTS_LEN);
+       err |= __put_user(0,name->nodename+__OLD_UTS_LEN);
+       err |= __copy_to_user(&name->release,&system_utsname.release,
+                               __OLD_UTS_LEN);
+       err |= __put_user(0,name->release+__OLD_UTS_LEN);
+       err |= __copy_to_user(&name->version,&system_utsname.version,
+                               __OLD_UTS_LEN);
+       err |= __put_user(0,name->version+__OLD_UTS_LEN);
         { 
                 char *arch = "x86_64";
                 if (personality(current->personality) == PER_LINUX32)
                         arch = "i686";
                 
-                __copy_to_user(&name->machine,arch,strlen(arch)+1);
+                err |= __copy_to_user(&name->machine,arch,strlen(arch)+1);
         }
        
         up_read(&uts_sem);
         
-        error = error ? -EFAULT : 0;
+        err = err ? -EFAULT : 0;
         
-        return error;
+        return err;
 }
 
 long sys32_uname(struct old_utsname __user * name)
@@ -831,7 +837,7 @@ long sys32_ustat(unsigned dev, struct ustat32 __user *u32p)
        
        seg = get_fs(); 
        set_fs(KERNEL_DS); 
-       ret = sys_ustat(dev,&u); 
+       ret = sys_ustat(dev, (struct ustat __user *)&u);
        set_fs(seg);
        if (ret >= 0) { 
                if (!access_ok(VERIFY_WRITE,u32p,sizeof(struct ustat32)) || 
index b5aaeafc1cd3cf5542fb7b4acab68b7b943fe157..3c7cbff04d3d78a2d8f5a73ecf8dbc1438475152 100644 (file)
@@ -11,7 +11,7 @@ obj-y := process.o signal.o entry.o traps.o irq.o \
                pci-dma.o pci-nommu.o alternative.o
 
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
-obj-$(CONFIG_X86_MCE)         += mce.o
+obj-$(CONFIG_X86_MCE)          += mce.o therm_throt.o
 obj-$(CONFIG_X86_MCE_INTEL)    += mce_intel.o
 obj-$(CONFIG_X86_MCE_AMD)      += mce_amd.o
 obj-$(CONFIG_MTRR)             += ../../i386/kernel/cpu/mtrr/
@@ -20,8 +20,8 @@ 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_X86_LOCAL_APIC)   += apic.o  nmi.o
-obj-$(CONFIG_X86_IO_APIC)      += io_apic.o mpparse.o \
+obj-y                          += apic.o  nmi.o
+obj-y                          += io_apic.o mpparse.o \
                genapic.o genapic_cluster.o genapic_flat.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel.o crash.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
@@ -39,12 +39,14 @@ obj-$(CONFIG_K8_NB)         += k8.o
 obj-$(CONFIG_AUDIT)            += audit.o
 
 obj-$(CONFIG_MODULES)          += module.o
+obj-$(CONFIG_PCI)              += early-quirks.o
 
 obj-y                          += topology.o
 obj-y                          += intel_cacheinfo.o
 
 CFLAGS_vsyscall.o              := $(PROFILING) -g0
 
+therm_throt-y                   += ../../i386/kernel/cpu/mcheck/therm_throt.o
 bootflag-y                     += ../../i386/kernel/bootflag.o
 cpuid-$(subst m,y,$(CONFIG_X86_CPUID))  += ../../i386/kernel/cpuid.o
 topology-y                     += ../../i386/kernel/topology.o
@@ -54,4 +56,3 @@ 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
-
index 58af8e73738bd5cf51dc9b0a7884bb0fbb66d154..b487396c4c5bc4e8e3310a9702e03ea5b4e88ed9 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/pci_ids.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
+#include <linux/ioport.h>
 #include <asm/e820.h>
 #include <asm/io.h>
 #include <asm/proto.h>
@@ -33,6 +34,18 @@ int fallback_aper_force __initdata = 0;
 
 int fix_aperture __initdata = 1;
 
+static struct resource gart_resource = {
+       .name   = "GART",
+       .flags  = IORESOURCE_MEM,
+};
+
+static void __init insert_aperture_resource(u32 aper_base, u32 aper_size)
+{
+       gart_resource.start = aper_base;
+       gart_resource.end = aper_base + aper_size - 1;
+       insert_resource(&iomem_resource, &gart_resource);
+}
+
 /* This code runs before the PCI subsystem is initialized, so just
    access the northbridge directly. */
 
@@ -48,7 +61,7 @@ static u32 __init allocate_aperture(void)
 
        /* 
         * Aperture has to be naturally aligned. This means an 2GB aperture won't
-        * have much chances to find a place in the lower 4GB of memory.
+        * have much chance of finding a place in the lower 4GB of memory.
         * Unfortunately we cannot move it up because that would make the
         * IOMMU useless.
         */
@@ -62,6 +75,7 @@ static u32 __init allocate_aperture(void)
        }
        printk("Mapping aperture over %d KB of RAM @ %lx\n",
               aper_size >> 10, __pa(p)); 
+       insert_aperture_resource((u32)__pa(p), aper_size);
        return (u32)__pa(p); 
 }
 
@@ -198,7 +212,7 @@ void __init iommu_hole_init(void)
        u64 aper_base, last_aper_base = 0;
        int valid_agp = 0;
 
-       if (iommu_aperture_disabled || !fix_aperture)
+       if (iommu_aperture_disabled || !fix_aperture || !early_pci_allowed())
                return;
 
        printk("Checking aperture...\n"); 
@@ -233,8 +247,13 @@ void __init iommu_hole_init(void)
                last_aper_base = aper_base;
        } 
 
-       if (!fix && !fallback_aper_force) 
+       if (!fix && !fallback_aper_force) {
+               if (last_aper_base) {
+                       unsigned long n = (32 * 1024 * 1024) << last_aper_order;
+                       insert_aperture_resource((u32)last_aper_base, n);
+               }
                return; 
+       }
 
        if (!fallback_aper_force)
                aper_alloc = search_agp_bridge(&aper_order, &valid_agp); 
index 2b8cef037a6544046fc71000fea9c8e9874a7df9..135ff25e6b449ad613671756ff3ba0c0b37ae018 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/sysdev.h>
 #include <linux/module.h>
+#include <linux/ioport.h>
 
 #include <asm/atomic.h>
 #include <asm/smp.h>
 #include <asm/idle.h>
 #include <asm/proto.h>
 #include <asm/timex.h>
+#include <asm/apic.h>
 
+int apic_mapped;
 int apic_verbosity;
 int apic_runs_main_timer;
 int apic_calibrate_pmtmr __initdata;
 
 int disable_apic_timer __initdata;
 
+static struct resource lapic_resource = {
+       .name = "Local APIC",
+       .flags = IORESOURCE_MEM | IORESOURCE_BUSY,
+};
+
 /*
  * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
  * IPIs in place of local APIC timers
@@ -136,72 +144,40 @@ void clear_local_APIC(void)
        apic_read(APIC_ESR);
 }
 
-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);
-       }
-}
-
 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_QUIET, "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(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(APIC_LVT0, value);
-               }
-               else {
-                       /* Disable LVT0 */
-                       apic_write(APIC_LVT0, APIC_LVT_MASKED);
-               }
+       /* 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(APIC_SPIV, value);
 
-               /* For LVT1 make it edge triggered, active high, nmi and enabled */
-               value = apic_read(APIC_LVT1);
-               value &= ~(
-                       APIC_MODE_MASK | APIC_SEND_PENDING |
+       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);
+                       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(APIC_LVT1, value);
+               value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
+               apic_write(APIC_LVT0, value);
+       } else {
+               /* Disable LVT0 */
+               apic_write(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(APIC_LVT1, value);
 }
 
 void disable_local_APIC(void)
@@ -297,8 +273,6 @@ void __init sync_Arb_IDs(void)
                                | APIC_DM_INIT);
 }
 
-extern void __error_in_apic_c (void);
-
 /*
  * An initial setup of the virtual wire mode.
  */
@@ -345,8 +319,7 @@ void __cpuinit setup_local_APIC (void)
 
        value = apic_read(APIC_LVR);
 
-       if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
-               __error_in_apic_c();
+       BUILD_BUG_ON((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f);
 
        /*
         * Double-check whether this APIC is really registered.
@@ -399,32 +372,8 @@ void __cpuinit setup_local_APIC (void)
         */
        value |= APIC_SPIV_APIC_ENABLED;
 
-       /*
-        * Some unknown Intel IO/APIC (or APIC) errata is biting us with
-        * certain networking cards. If high frequency interrupts are
-        * happening on a particular IOAPIC pin, plus the IOAPIC routing
-        * entry is masked/unmasked at a high rate as well then sooner or
-        * later IOAPIC line gets 'stuck', no more interrupts are received
-        * from the device. If focus CPU is disabled then the hang goes
-        * away, oh well :-(
-        *
-        * [ This bug can be reproduced easily with a level-triggered
-        *   PCI Ne2000 networking cards and PII/PIII processors, dual
-        *   BX chipset. ]
-        */
-       /*
-        * Actually disabling the focus CPU check just makes the hang less
-        * frequent as it makes the interrupt distributon model be more
-        * 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
+       /* We always use processor focus */
+
        /*
         * Set spurious IRQ vector
         */
@@ -442,7 +391,7 @@ void __cpuinit setup_local_APIC (void)
         * TODO: set up through-local-APIC from through-I/O-APIC? --macro
         */
        value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
-       if (!smp_processor_id() && (pic_mode || !value)) {
+       if (!smp_processor_id() && !value) {
                value = APIC_DM_EXTINT;
                apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", smp_processor_id());
        } else {
@@ -479,8 +428,7 @@ void __cpuinit setup_local_APIC (void)
        }
 
        nmi_watchdog_default();
-       if (nmi_watchdog == NMI_LOCAL_APIC)
-               setup_apic_nmi_watchdog();
+       setup_apic_nmi_watchdog(NULL);
        apic_pm_activate();
 }
 
@@ -527,8 +475,7 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
        apic_pm_state.apic_tmict = apic_read(APIC_TMICT);
        apic_pm_state.apic_tdcr = apic_read(APIC_TDCR);
        apic_pm_state.apic_thmr = apic_read(APIC_LVTTHMR);
-       local_save_flags(flags);
-       local_irq_disable();
+       local_irq_save(flags);
        disable_local_APIC();
        local_irq_restore(flags);
        return 0;
@@ -606,18 +553,24 @@ static void apic_pm_activate(void) { }
 
 static int __init apic_set_verbosity(char *str)
 {
+       if (str == NULL)  {
+               skip_ioapic_setup = 0;
+               ioapic_force = 1;
+               return 0;
+       }
        if (strcmp("debug", str) == 0)
                apic_verbosity = APIC_DEBUG;
        else if (strcmp("verbose", str) == 0)
                apic_verbosity = APIC_VERBOSE;
-       else
+       else {
                printk(KERN_WARNING "APIC Verbosity level %s not recognised"
-                               " use apic=verbose or apic=debug", str);
+                               " use apic=verbose or apic=debug\n", str);
+               return -EINVAL;
+       }
 
-       return 1;
+       return 0;
 }
-
-__setup("apic=", apic_set_verbosity);
+early_param("apic", apic_set_verbosity);
 
 /*
  * Detect and enable local APICs on non-SMP boards.
@@ -638,6 +591,40 @@ static int __init detect_init_APIC (void)
        return 0;
 }
 
+#ifdef CONFIG_X86_IO_APIC
+static struct resource * __init ioapic_setup_resources(void)
+{
+#define IOAPIC_RESOURCE_NAME_SIZE 11
+       unsigned long n;
+       struct resource *res;
+       char *mem;
+       int i;
+
+       if (nr_ioapics <= 0)
+               return NULL;
+
+       n = IOAPIC_RESOURCE_NAME_SIZE + sizeof(struct resource);
+       n *= nr_ioapics;
+
+       res = alloc_bootmem(n);
+
+       if (!res)
+               return NULL;
+
+       memset(res, 0, n);
+       mem = (void *)&res[nr_ioapics];
+
+       for (i = 0; i < nr_ioapics; i++) {
+               res[i].name = mem;
+               res[i].flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               snprintf(mem, IOAPIC_RESOURCE_NAME_SIZE, "IOAPIC %u", i);
+               mem += IOAPIC_RESOURCE_NAME_SIZE;
+       }
+
+       return res;
+}
+#endif
+
 void __init init_apic_mappings(void)
 {
        unsigned long apic_phys;
@@ -654,19 +641,26 @@ void __init init_apic_mappings(void)
                apic_phys = mp_lapic_addr;
 
        set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
+       apic_mapped = 1;
        apic_printk(APIC_VERBOSE,"mapped APIC to %16lx (%16lx)\n", APIC_BASE, apic_phys);
 
+       /* Put local APIC into the resource map. */
+       lapic_resource.start = apic_phys;
+       lapic_resource.end = lapic_resource.start + PAGE_SIZE - 1;
+       insert_resource(&iomem_resource, &lapic_resource);
+
        /*
         * Fetch the APIC ID of the BSP in case we have a
         * default configuration (or the MP table is broken).
         */
        boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
 
-#ifdef CONFIG_X86_IO_APIC
        {
                unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
                int i;
+               struct resource *ioapic_res;
 
+               ioapic_res = ioapic_setup_resources();
                for (i = 0; i < nr_ioapics; i++) {
                        if (smp_found_config) {
                                ioapic_phys = mp_ioapics[i].mpc_apicaddr;
@@ -678,9 +672,15 @@ void __init init_apic_mappings(void)
                        apic_printk(APIC_VERBOSE,"mapped IOAPIC to %016lx (%016lx)\n",
                                        __fix_to_virt(idx), ioapic_phys);
                        idx++;
+
+                       if (ioapic_res) {
+                               ioapic_res->start = ioapic_phys;
+                               ioapic_res->end = ioapic_phys + (4 * 1024) - 1;
+                               insert_resource(&iomem_resource, ioapic_res);
+                               ioapic_res++;
+                       }
                }
        }
-#endif
 }
 
 /*
@@ -951,7 +951,7 @@ void smp_local_timer_interrupt(struct pt_regs *regs)
         * We take the 'long' return path, and there every subsystem
         * grabs the appropriate locks (kernel lock/ irq lock).
         *
-        * we might want to decouple profiling from the 'long path',
+        * 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),
@@ -1123,19 +1123,15 @@ int __init APIC_init_uniprocessor (void)
 
        verify_local_APIC();
 
-       connect_bsp_APIC();
-
        phys_cpu_present_map = physid_mask_of_physid(boot_cpu_id);
        apic_write(APIC_ID, SET_APIC_ID(boot_cpu_id));
 
        setup_local_APIC();
 
-#ifdef CONFIG_X86_IO_APIC
        if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
-                       setup_IO_APIC();
+               setup_IO_APIC();
        else
                nr_ioapics = 0;
-#endif
        setup_boot_APIC_clock();
        check_nmi_watchdog();
        return 0;
@@ -1144,14 +1140,17 @@ int __init APIC_init_uniprocessor (void)
 static __init int setup_disableapic(char *str) 
 { 
        disable_apic = 1;
-       return 1;
-} 
+       clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+       return 0;
+}
+early_param("disableapic", setup_disableapic);
 
+/* same as disableapic, for compatibility */
 static __init int setup_nolapic(char *str) 
 { 
-       disable_apic = 1;
-       return 1;
+       return setup_disableapic(str);
 } 
+early_param("nolapic", setup_nolapic);
 
 static __init int setup_noapictimer(char *str) 
 { 
@@ -1184,11 +1183,5 @@ static __init int setup_apicpmtimer(char *s)
 }
 __setup("apicpmtimer", setup_apicpmtimer);
 
-/* dummy parsing: see setup.c */
-
-__setup("disableapic", setup_disableapic); 
-__setup("nolapic", setup_nolapic);  /* same as disableapic, for compatibility */
-
 __setup("noapictimer", setup_noapictimer); 
 
-/* no "lapic" flag - we only use the lapic when the BIOS tells us so. */
index d8d5750d6106a1270817a360868cdbfb3d281338..3525f884af82772592adf860d926de115b3b2d8a 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/nmi.h>
 #include <asm/hw_irq.h>
 #include <asm/mach_apic.h>
+#include <asm/kdebug.h>
 
 /* This keeps a track of which one is crashing cpu. */
 static int crashing_cpu;
@@ -68,7 +69,7 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
         * for the data I pass, and I need tags
         * on the data to indicate what information I have
         * squirrelled away.  ELF notes happen to provide
-        * all of that that no need to invent something new.
+        * all of that, no need to invent something new.
         */
 
        buf = (u32*)per_cpu_ptr(crash_notes, cpu);
@@ -95,15 +96,25 @@ static void crash_save_self(struct pt_regs *regs)
 #ifdef CONFIG_SMP
 static atomic_t waiting_for_crash_ipi;
 
-static int crash_nmi_callback(struct pt_regs *regs, int cpu)
+static int crash_nmi_callback(struct notifier_block *self,
+                               unsigned long val, void *data)
 {
+       struct pt_regs *regs;
+       int cpu;
+
+       if (val != DIE_NMI_IPI)
+               return NOTIFY_OK;
+
+       regs = ((struct die_args *)data)->regs;
+       cpu = raw_smp_processor_id();
+
        /*
         * Don't do anything if this handler is invoked on crashing cpu.
         * Otherwise, system will completely hang. Crashing cpu can get
         * an NMI if system was initially booted with nmi_watchdog parameter.
         */
        if (cpu == crashing_cpu)
-               return 1;
+               return NOTIFY_STOP;
        local_irq_disable();
 
        crash_save_this_cpu(regs, cpu);
@@ -127,12 +138,17 @@ static void smp_send_nmi_allbutself(void)
  * cpu hotplug shouldn't matter.
  */
 
+static struct notifier_block crash_nmi_nb = {
+       .notifier_call = crash_nmi_callback,
+};
+
 static void nmi_shootdown_cpus(void)
 {
        unsigned long msecs;
 
        atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
-       set_nmi_callback(crash_nmi_callback);
+       if (register_die_notifier(&crash_nmi_nb))
+               return;         /* return what? */
 
        /*
         * Ensure the new callback function is set before sending
@@ -178,9 +194,7 @@ void machine_crash_shutdown(struct pt_regs *regs)
        if(cpu_has_apic)
                 disable_local_APIC();
 
-#if defined(CONFIG_X86_IO_APIC)
        disable_IO_APIC();
-#endif
 
        crash_save_self(regs);
 }
index 708a3cd9a27ec01129eeb3df6f7e32b1936fb38a..b3f0908668ece23c11fc4d42675f011aab808821 100644 (file)
@@ -25,6 +25,8 @@
 #include <asm/bootsetup.h>
 #include <asm/sections.h>
 
+struct e820map e820 __initdata;
+
 /* 
  * PFN of last memory page.
  */
@@ -41,7 +43,7 @@ unsigned long end_pfn_map;
 /* 
  * Last pfn which the user wants to use.
  */
-unsigned long end_user_pfn = MAXMEM>>PAGE_SHIFT;  
+static unsigned long __initdata end_user_pfn = MAXMEM>>PAGE_SHIFT;
 
 extern struct resource code_resource, data_resource;
 
@@ -70,12 +72,7 @@ static inline int bad_addr(unsigned long *addrp, unsigned long size)
                return 1;
        } 
 #endif
-       /* kernel code + 640k memory hole (later should not be needed, but 
-          be paranoid for now) */
-       if (last >= 640*1024 && addr < 1024*1024) {
-               *addrp = 1024*1024;
-               return 1;
-       }
+       /* kernel code */
        if (last >= __pa_symbol(&_text) && last < __pa_symbol(&_end)) {
                *addrp = __pa_symbol(&_end);
                return 1;
@@ -165,59 +162,14 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsi
        return -1UL;            
 } 
 
-/* 
- * Free bootmem based on the e820 table for a node.
- */
-void __init e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end)
-{
-       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 && last-addr >= PAGE_SIZE)
-                       free_bootmem_node(pgdat, addr, last-addr);
-       }
-}
-
 /*
  * Find the highest page frame number we have available
  */
 unsigned long __init e820_end_of_ram(void)
 {
-       int i;
        unsigned long end_pfn = 0;
+       end_pfn = find_max_pfn_with_active_regions();
        
-       for (i = 0; i < e820.nr_map; i++) {
-               struct e820entry *ei = &e820.map[i]; 
-               unsigned long start, end;
-
-               start = round_up(ei->addr, PAGE_SIZE); 
-               end = round_down(ei->addr + ei->size, PAGE_SIZE); 
-               if (start >= end)
-                       continue;
-               if (ei->type == E820_RAM) { 
-               if (end > end_pfn<<PAGE_SHIFT)
-                       end_pfn = end>>PAGE_SHIFT;
-               } else { 
-                       if (end > end_pfn_map<<PAGE_SHIFT) 
-                               end_pfn_map = end>>PAGE_SHIFT;
-               } 
-       }
-
        if (end_pfn > end_pfn_map) 
                end_pfn_map = end_pfn;
        if (end_pfn_map > MAXMEM>>PAGE_SHIFT)
@@ -227,43 +179,10 @@ unsigned long __init e820_end_of_ram(void)
        if (end_pfn > end_pfn_map) 
                end_pfn = end_pfn_map; 
 
+       printk("end_pfn_map = %lu\n", end_pfn_map);
        return end_pfn; 
 }
 
-/* 
- * Compute how much memory is missing in a range.
- * Unlike the other functions in this file the arguments are in page numbers.
- */
-unsigned long __init
-e820_hole_size(unsigned long start_pfn, unsigned long end_pfn)
-{
-       unsigned long ram = 0;
-       unsigned long start = start_pfn << PAGE_SHIFT;
-       unsigned long end = end_pfn << PAGE_SHIFT;
-       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) >> PAGE_SHIFT;
-}
-
 /*
  * Mark e820 reserved areas as busy for the resource manager.
  */
@@ -345,6 +264,49 @@ void __init e820_mark_nosave_regions(void)
        }
 }
 
+/* Walk the e820 map and register active regions within a node */
+void __init
+e820_register_active_regions(int nid, unsigned long start_pfn,
+                                                       unsigned long end_pfn)
+{
+       int i;
+       unsigned long ei_startpfn, ei_endpfn;
+       for (i = 0; i < e820.nr_map; i++) {
+               struct e820entry *ei = &e820.map[i];
+               ei_startpfn = round_up(ei->addr, PAGE_SIZE) >> PAGE_SHIFT;
+               ei_endpfn = round_down(ei->addr + ei->size, PAGE_SIZE)
+                                                               >> PAGE_SHIFT;
+
+               /* Skip map entries smaller than a page */
+               if (ei_startpfn > ei_endpfn)
+                       continue;
+
+               /* Check if end_pfn_map should be updated */
+               if (ei->type != E820_RAM && ei_endpfn > end_pfn_map)
+                       end_pfn_map = ei_endpfn;
+
+               /* Skip if map is outside the node */
+               if (ei->type != E820_RAM ||
+                               ei_endpfn <= start_pfn ||
+                               ei_startpfn >= end_pfn)
+                       continue;
+
+               /* Check for overlaps */
+               if (ei_startpfn < start_pfn)
+                       ei_startpfn = start_pfn;
+               if (ei_endpfn > end_pfn)
+                       ei_endpfn = end_pfn;
+
+               /* Obey end_user_pfn to save on memmap */
+               if (ei_startpfn >= end_user_pfn)
+                       continue;
+               if (ei_endpfn > end_user_pfn)
+                       ei_endpfn = end_user_pfn;
+
+               add_active_range(nid, ei_startpfn, ei_endpfn);
+       }
+}
+
 /* 
  * Add a memory region to the kernel e820 map.
  */ 
@@ -565,13 +527,6 @@ static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
  * If we're lucky and live on a modern system, the setup code
  * will have given us a memory map that we can use to properly
  * set up memory.  If we aren't, we'll fake a memory map.
- *
- * We check to see that the memory map contains at least 2 elements
- * before we'll use it, because the detection code in setup.S may
- * not be perfect and most every PC known to man has two memory
- * regions: one from 0 to 640k, and one from 1mb up.  (The IBM
- * thinkpad 560x, for example, does not cooperate with the memory
- * detection code.)
  */
 static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
 {
@@ -589,34 +544,19 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
                if (start > end)
                        return -1;
 
-               /*
-                * Some BIOSes claim RAM in the 640k - 1M region.
-                * Not right. Fix it up.
-                * 
-                * This should be removed on Hammer which is supposed to not
-                * have non e820 covered ISA mappings there, but I had some strange
-                * problems so it stays for now.  -AK
-                */
-               if (type == E820_RAM) {
-                       if (start < 0x100000ULL && end > 0xA0000ULL) {
-                               if (start < 0xA0000ULL)
-                                       add_memory_region(start, 0xA0000ULL-start, type);
-                               if (end <= 0x100000ULL)
-                                       continue;
-                               start = 0x100000ULL;
-                               size = end - start;
-                       }
-               }
-
                add_memory_region(start, size, type);
        } while (biosmap++,--nr_map);
        return 0;
 }
 
-void __init setup_memory_region(void)
+void early_panic(char *msg)
 {
-       char *who = "BIOS-e820";
+       early_printk(msg);
+       panic(msg);
+}
 
+void __init setup_memory_region(void)
+{
        /*
         * Try to copy the BIOS-supplied E820-map.
         *
@@ -624,51 +564,70 @@ void __init setup_memory_region(void)
         * the next section from 1mb->appropriate_mem_k
         */
        sanitize_e820_map(E820_MAP, &E820_MAP_NR);
-       if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
-               unsigned long mem_size;
-
-               /* compare results from other methods and take the greater */
-               if (ALT_MEM_K < EXT_MEM_K) {
-                       mem_size = EXT_MEM_K;
-                       who = "BIOS-88";
-               } else {
-                       mem_size = ALT_MEM_K;
-                       who = "BIOS-e801";
-               }
-
-               e820.nr_map = 0;
-               add_memory_region(0, LOWMEMSIZE(), E820_RAM);
-               add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
-       }
+       if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0)
+               early_panic("Cannot find a valid memory map");
        printk(KERN_INFO "BIOS-provided physical RAM map:\n");
-       e820_print_map(who);
+       e820_print_map("BIOS-e820");
 }
 
-void __init parse_memopt(char *p, char **from) 
-{ 
-       end_user_pfn = memparse(p, from);
+static int __init parse_memopt(char *p)
+{
+       if (!p)
+               return -EINVAL;
+       end_user_pfn = memparse(p, &p);
        end_user_pfn >>= PAGE_SHIFT;    
+       return 0;
 } 
+early_param("mem", parse_memopt);
 
-void __init parse_memmapopt(char *p, char **from)
+static int userdef __initdata;
+
+static int __init parse_memmap_opt(char *p)
 {
+       char *oldp;
        unsigned long long start_at, mem_size;
 
-       mem_size = memparse(p, from);
-       p = *from;
+       if (!strcmp(p, "exactmap")) {
+#ifdef CONFIG_CRASH_DUMP
+               /* If we are doing a crash dump, we
+                * still need to know the real mem
+                * size before original memory map is
+                * reset.
+                */
+               saved_max_pfn = e820_end_of_ram();
+#endif
+               end_pfn_map = 0;
+               e820.nr_map = 0;
+               userdef = 1;
+               return 0;
+       }
+
+       oldp = p;
+       mem_size = memparse(p, &p);
+       if (p == oldp)
+               return -EINVAL;
        if (*p == '@') {
-               start_at = memparse(p+1, from);
+               start_at = memparse(p+1, &p);
                add_memory_region(start_at, mem_size, E820_RAM);
        } else if (*p == '#') {
-               start_at = memparse(p+1, from);
+               start_at = memparse(p+1, &p);
                add_memory_region(start_at, mem_size, E820_ACPI);
        } else if (*p == '$') {
-               start_at = memparse(p+1, from);
+               start_at = memparse(p+1, &p);
                add_memory_region(start_at, mem_size, E820_RESERVED);
        } else {
                end_user_pfn = (mem_size >> PAGE_SHIFT);
        }
-       p = *from;
+       return *p == '\0' ? 0 : -EINVAL;
+}
+early_param("memmap", parse_memmap_opt);
+
+void finish_e820_parsing(void)
+{
+       if (userdef) {
+               printk(KERN_INFO "user-defined physical RAM map:\n");
+               e820_print_map("user");
+       }
 }
 
 unsigned long pci_mem_start = 0xaeedbabe;
diff --git a/arch/x86_64/kernel/early-quirks.c b/arch/x86_64/kernel/early-quirks.c
new file mode 100644 (file)
index 0000000..208e38a
--- /dev/null
@@ -0,0 +1,122 @@
+/* Various workarounds for chipset bugs.
+   This code runs very early and can't use the regular PCI subsystem
+   The entries are keyed to PCI bridges which usually identify chipsets
+   uniquely.
+   This is only for whole classes of chipsets with specific problems which
+   need early invasive action (e.g. before the timers are initialized).
+   Most PCI device specific workarounds can be done later and should be
+   in standard PCI quirks
+   Mainboard specific bugs should be handled by DMI entries.
+   CPU specific bugs in setup.c */
+
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <linux/pci_ids.h>
+#include <asm/pci-direct.h>
+#include <asm/proto.h>
+#include <asm/dma.h>
+
+static void via_bugs(void)
+{
+#ifdef CONFIG_IOMMU
+       if ((end_pfn > MAX_DMA32_PFN ||  force_iommu) &&
+           !iommu_aperture_allowed) {
+               printk(KERN_INFO
+  "Looks like a VIA chipset. Disabling IOMMU. Override with iommu=allowed\n");
+               iommu_aperture_disabled = 1;
+       }
+#endif
+}
+
+#ifdef CONFIG_ACPI
+
+static int nvidia_hpet_detected __initdata;
+
+static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
+{
+       nvidia_hpet_detected = 1;
+       return 0;
+}
+#endif
+
+static void nvidia_bugs(void)
+{
+#ifdef CONFIG_ACPI
+       /*
+        * All timer overrides on Nvidia are
+        * wrong unless HPET is enabled.
+        */
+       nvidia_hpet_detected = 0;
+       acpi_table_parse(ACPI_HPET, nvidia_hpet_check);
+       if (nvidia_hpet_detected == 0) {
+               acpi_skip_timer_override = 1;
+               printk(KERN_INFO "Nvidia board "
+                      "detected. Ignoring ACPI "
+                      "timer override.\n");
+       }
+#endif
+       /* RED-PEN skip them on mptables too? */
+
+}
+
+static void ati_bugs(void)
+{
+#if 1 /* for testing */
+       printk("ATI board detected\n");
+#endif
+       /* No bugs right now */
+}
+
+struct chipset {
+       u16 vendor;
+       void (*f)(void);
+};
+
+static struct chipset early_qrk[] = {
+       { PCI_VENDOR_ID_NVIDIA, nvidia_bugs },
+       { PCI_VENDOR_ID_VIA, via_bugs },
+       { PCI_VENDOR_ID_ATI, ati_bugs },
+       {}
+};
+
+void __init early_quirks(void)
+{
+       int num, slot, func;
+
+       if (!early_pci_allowed())
+               return;
+
+       /* Poor man's PCI discovery */
+       for (num = 0; num < 32; num++) {
+               for (slot = 0; slot < 32; slot++) {
+                       for (func = 0; func < 8; func++) {
+                               u32 class;
+                               u32 vendor;
+                               u8 type;
+                               int i;
+                               class = read_pci_config(num,slot,func,
+                                                       PCI_CLASS_REVISION);
+                               if (class == 0xffffffff)
+                                       break;
+
+                               if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
+                                       continue;
+
+                               vendor = read_pci_config(num, slot, func,
+                                                        PCI_VENDOR_ID);
+                               vendor &= 0xffff;
+
+                               for (i = 0; early_qrk[i].f; i++)
+                                       if (early_qrk[i].vendor == vendor) {
+                                               early_qrk[i].f();
+                                               return;
+                                       }
+
+                               type = read_pci_config_byte(num, slot, func,
+                                                           PCI_HEADER_TYPE);
+                               if (!(type & 0x80))
+                                       break;
+                       }
+               }
+       }
+}
index 140051e07fa64c7f07e2fd8b5e099ceaf15c3860..e22ecd54870d8e818dc0bc2563a8194a7699def2 100644 (file)
@@ -215,20 +215,16 @@ void early_printk(const char *fmt, ...)
 
 static int __initdata keep_early;
 
-int __init setup_early_printk(char *opt)
+static int __init setup_early_printk(char *buf)
 {
-       char *space;
-       char buf[256];
+       if (!buf)
+               return 0;
 
        if (early_console_initialized)
-               return 1;
-
-       strlcpy(buf,opt,sizeof(buf));
-       space = strchr(buf, ' ');
-       if (space)
-               *space = 0;
+               return 0;
+       early_console_initialized = 1;
 
-       if (strstr(buf,"keep"))
+       if (!strcmp(buf,"keep"))
                keep_early = 1;
 
        if (!strncmp(buf, "serial", 6)) {
@@ -248,11 +244,12 @@ int __init setup_early_printk(char *opt)
                early_console = &simnow_console;
                keep_early = 1;
        }
-       early_console_initialized = 1;
        register_console(early_console);
        return 0;
 }
 
+early_param("earlyprintk", setup_early_printk);
+
 void __init disable_early_printk(void)
 {
        if (!early_console_initialized || !early_console)
@@ -266,4 +263,3 @@ void __init disable_early_printk(void)
        }
 }
 
-__setup("earlyprintk=", setup_early_printk);
index aa8d8939abc1692df22e7000c226095a44167678..2802524104f32da51e268cdc6b540efccccb93e1 100644 (file)
@@ -4,8 +4,6 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 2000, 2001, 2002  Andi Kleen SuSE Labs
  *  Copyright (C) 2000  Pavel Machek <pavel@suse.cz>
- * 
- *  $Id$
  */
 
 /*
  * at the top of the kernel process stack.     
  * - partial stack frame: partially saved registers upto R11.
  * - full stack frame: Like partial stack frame, but all register saved. 
- *     
- * TODO:        
- * - schedule it carefully for the final hardware.
+ *
+ * Some macro usage:
+ * - CFI macros are used to generate dwarf2 unwind information for better
+ * backtraces. They don't change any code.
+ * - SAVE_ALL/RESTORE_ALL - Save/restore all registers
+ * - SAVE_ARGS/RESTORE_ARGS - Save/restore registers that C functions modify.
+ * There are unfortunately lots of special cases where some registers
+ * not touched. The macro is a big mess that should be cleaned up.
+ * - SAVE_REST/RESTORE_REST - Handle the registers not saved by SAVE_ARGS.
+ * Gives a full stack frame.
+ * - ENTRY/END Define functions in the symbol table.
+ * - FIXUP_TOP_OF_STACK/RESTORE_TOP_OF_STACK - Fix up the hardware stack
+ * frame that is otherwise undefined after a SYSCALL
+ * - TRACE_IRQ_* - Trace hard interrupt state for lock debugging.
+ * - errorentry/paranoidentry/zeroentry - Define exception entry points.
  */
 
-#define ASSEMBLY 1
 #include <linux/linkage.h>
 #include <asm/segment.h>
-#include <asm/smp.h>
 #include <asm/cache.h>
 #include <asm/errno.h>
 #include <asm/dwarf2.h>
        .macro  CFI_DEFAULT_STACK start=1
        .if \start
        CFI_STARTPROC   simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA     rsp,SS+8
        .else
        CFI_DEF_CFA_OFFSET SS+8
 /* rdi:        prev */ 
 ENTRY(ret_from_fork)
        CFI_DEFAULT_STACK
+       push kernel_eflags(%rip)
+       CFI_ADJUST_CFA_OFFSET 4
+       popf                            # reset kernel eflags
+       CFI_ADJUST_CFA_OFFSET -4
        call schedule_tail
        GET_THREAD_INFO(%rcx)
        testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
@@ -199,6 +212,7 @@ END(ret_from_fork)
 
 ENTRY(system_call)
        CFI_STARTPROC   simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA     rsp,PDA_STACKOFFSET
        CFI_REGISTER    rip,rcx
        /*CFI_REGISTER  rflags,r11*/
@@ -316,6 +330,7 @@ END(system_call)
  */    
 ENTRY(int_ret_from_sys_call)
        CFI_STARTPROC   simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA     rsp,SS+8-ARGOFFSET
        /*CFI_REL_OFFSET        ss,SS-ARGOFFSET*/
        CFI_REL_OFFSET  rsp,RSP-ARGOFFSET
@@ -476,6 +491,7 @@ END(stub_rt_sigreturn)
  */
        .macro _frame ref
        CFI_STARTPROC simple
+       CFI_SIGNAL_FRAME
        CFI_DEF_CFA rsp,SS+8-\ref
        /*CFI_REL_OFFSET ss,SS-\ref*/
        CFI_REL_OFFSET rsp,RSP-\ref
@@ -511,7 +527,12 @@ END(stub_rt_sigreturn)
        testl $3,CS(%rdi)
        je 1f
        swapgs  
-1:     incl    %gs:pda_irqcount        # RED-PEN should check preempt count
+       /* irqcount is used to check if a CPU is already on an interrupt
+          stack or not. While this is essentially redundant with preempt_count
+          it is a little cheaper to use a separate counter in the PDA
+          (short of moving irq_enter into assembly, which would be too
+           much work) */
+1:     incl    %gs:pda_irqcount
        cmoveq %gs:pda_irqstackptr,%rsp
        push    %rbp                    # backlink for old unwinder
        /*
@@ -619,8 +640,7 @@ retint_signal:
 #ifdef CONFIG_PREEMPT
        /* Returning to kernel space. Check if we need preemption */
        /* rcx:  threadinfo. interrupts off. */
-       .p2align
-retint_kernel: 
+ENTRY(retint_kernel)
        cmpl $0,threadinfo_preempt_count(%rcx)
        jnz  retint_restore_args
        bt  $TIF_NEED_RESCHED,threadinfo_flags(%rcx)
@@ -679,7 +699,6 @@ ENTRY(call_function_interrupt)
 END(call_function_interrupt)
 #endif
 
-#ifdef CONFIG_X86_LOCAL_APIC   
 ENTRY(apic_timer_interrupt)
        apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt
 END(apic_timer_interrupt)
@@ -691,7 +710,6 @@ END(error_interrupt)
 ENTRY(spurious_interrupt)
        apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
 END(spurious_interrupt)
-#endif
                                
 /*
  * Exception entry points.
@@ -768,7 +786,9 @@ paranoid_exit\trace:
        testl $3,CS(%rsp)
        jnz   paranoid_userspace\trace
 paranoid_swapgs\trace:
+       .if \trace
        TRACE_IRQS_IRETQ 0
+       .endif
        swapgs
 paranoid_restore\trace:
        RESTORE_ALL 8
@@ -814,7 +834,7 @@ paranoid_schedule\trace:
  * Exception entry point. This expects an error code/orig_rax on the stack
  * and the exception handler in %rax.  
  */                                            
-ENTRY(error_entry)
+KPROBE_ENTRY(error_entry)
        _frame RDI
        /* rdi slot contains rax, oldrax contains error code */
        cld     
@@ -898,7 +918,7 @@ error_kernelspace:
        cmpq $gs_change,RIP(%rsp)
         je   error_swapgs
        jmp  error_sti
-END(error_entry)
+KPROBE_END(error_entry)
        
        /* Reload gs selector with exception handling */
        /* edi:  new selector */ 
@@ -1020,8 +1040,7 @@ ENDPROC(execve)
 
 KPROBE_ENTRY(page_fault)
        errorentry do_page_fault
-END(page_fault)
-       .previous .text
+KPROBE_END(page_fault)
 
 ENTRY(coprocessor_error)
        zeroentry do_coprocessor_error
@@ -1042,8 +1061,7 @@ KPROBE_ENTRY(debug)
        CFI_ADJUST_CFA_OFFSET 8         
        paranoidentry do_debug, DEBUG_STACK
        paranoidexit
-END(debug)
-       .previous .text
+KPROBE_END(debug)
 
        /* runs on exception stack */   
 KPROBE_ENTRY(nmi)
@@ -1057,8 +1075,7 @@ KPROBE_ENTRY(nmi)
        jmp paranoid_exit1
        CFI_ENDPROC
 #endif
-END(nmi)
-       .previous .text
+KPROBE_END(nmi)
 
 KPROBE_ENTRY(int3)
        INTR_FRAME
@@ -1067,8 +1084,7 @@ KPROBE_ENTRY(int3)
        paranoidentry do_int3, DEBUG_STACK
        jmp paranoid_exit1
        CFI_ENDPROC
-END(int3)
-       .previous .text
+KPROBE_END(int3)
 
 ENTRY(overflow)
        zeroentry do_overflow
@@ -1116,8 +1132,7 @@ END(stack_segment)
 
 KPROBE_ENTRY(general_protection)
        errorentry do_general_protection
-END(general_protection)
-       .previous .text
+KPROBE_END(general_protection)
 
 ENTRY(alignment_check)
        errorentry do_alignment_check
index 3020917546de09ccd9b2432a0a06b8f6f2e1feaf..cdb90e671b88a7bc96064f6af8ca48afc4768dea 100644 (file)
@@ -118,7 +118,6 @@ struct genapic apic_cluster = {
        .name = "clustered",
        .int_delivery_mode = dest_Fixed,
        .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
-       .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_FIXED,
        .target_cpus = cluster_target_cpus,
        .apic_id_registered = cluster_apic_id_registered,
        .init_apic_ldr = cluster_init_apic_ldr,
index eb86d374813a3038c0b5299f6dae861b2bd4b33d..50ad153eaac416f42d7d93f90b23e23a11df07c7 100644 (file)
@@ -49,8 +49,7 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
        unsigned long cfg;
        unsigned long flags;
 
-       local_save_flags(flags);
-       local_irq_disable();
+       local_irq_save(flags);
 
        /*
         * Wait for idle.
@@ -121,7 +120,6 @@ struct genapic apic_flat =  {
        .name = "flat",
        .int_delivery_mode = dest_LowestPrio,
        .int_dest_mode = (APIC_DEST_LOGICAL != 0),
-       .int_delivery_dest = APIC_DEST_LOGICAL | APIC_DM_LOWEST,
        .target_cpus = flat_target_cpus,
        .apic_id_registered = flat_apic_id_registered,
        .init_apic_ldr = flat_init_apic_ldr,
@@ -180,7 +178,6 @@ struct genapic apic_physflat =  {
        .name = "physical flat",
        .int_delivery_mode = dest_Fixed,
        .int_dest_mode = (APIC_DEST_PHYSICAL != 0),
-       .int_delivery_dest = APIC_DEST_PHYSICAL | APIC_DM_FIXED,
        .target_cpus = physflat_target_cpus,
        .apic_id_registered = flat_apic_id_registered,
        .init_apic_ldr = flat_init_apic_ldr,/*not needed, but shouldn't hurt*/
index c9739ca81d062e31c30aed9ac07df6f921fe5c1f..1e6f80870679506482ef7d2714621e8ad4df4d08 100644 (file)
@@ -5,8 +5,6 @@
  *  Copyright (C) 2000 Pavel Machek <pavel@suse.cz>
  *  Copyright (C) 2000 Karsten Keil <kkeil@suse.de>
  *  Copyright (C) 2001,2002 Andi Kleen <ak@suse.de>
- *
- *  $Id: head.S,v 1.49 2002/03/19 17:39:25 ak Exp $
  */
 
 
@@ -187,12 +185,15 @@ startup_64:
        
        /* Finally jump to run C code and to be on real kernel address
         * Since we are running on identity-mapped space we have to jump
-        * to the full 64bit address , this is only possible as indirect
-        * jump
+        * to the full 64bit address, this is only possible as indirect
+        * jump.  In addition we need to ensure %cs is set so we make this
+        * a far return.
         */
        movq    initial_code(%rip),%rax
-       pushq   $0              # fake return address
-       jmp     *%rax
+       pushq   $0              # fake return address to stop unwinder
+       pushq   $__KERNEL_CS    # set correct cs
+       pushq   %rax            # target address in negative space
+       lretq
 
        /* SMP bootup changes these two */
        .align  8
@@ -371,7 +372,7 @@ ENTRY(cpu_gdt_table)
        .quad   0,0                     /* TSS */
        .quad   0,0                     /* LDT */
        .quad   0,0,0                   /* three TLS descriptors */ 
-       .quad   0                       /* unused */
+       .quad   0x0000f40000000000      /* node/CPU stored in limit */
 gdt_end:       
        /* asm/segment.h:GDT_ENTRIES must match this */ 
        /* This should be a multiple of the cache line size */
index 36647ce6aecbd696c97265b9e0d3862a723cc65a..9561eb3c5b5c5e78eed93277096eaf9d68752a64 100644 (file)
@@ -45,38 +45,16 @@ static void __init copy_bootdata(char *real_mode_data)
        new_data = *(int *) (x86_boot_params + NEW_CL_POINTER);
        if (!new_data) {
                if (OLD_CL_MAGIC != * (u16 *) OLD_CL_MAGIC_ADDR) {
-                       printk("so old bootloader that it does not support commandline?!\n");
                        return;
                }
                new_data = OLD_CL_BASE_ADDR + * (u16 *) OLD_CL_OFFSET;
-               printk("old bootloader convention, maybe loadlin?\n");
        }
        command_line = (char *) ((u64)(new_data));
        memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
-       printk("Bootdata ok (command line is %s)\n", saved_command_line);       
-}
-
-static void __init setup_boot_cpu_data(void)
-{
-       unsigned int dummy, eax;
-
-       /* get vendor info */
-       cpuid(0, (unsigned int *)&boot_cpu_data.cpuid_level,
-             (unsigned int *)&boot_cpu_data.x86_vendor_id[0],
-             (unsigned int *)&boot_cpu_data.x86_vendor_id[8],
-             (unsigned int *)&boot_cpu_data.x86_vendor_id[4]);
-
-       /* get cpu type */
-       cpuid(1, &eax, &dummy, &dummy,
-               (unsigned int *) &boot_cpu_data.x86_capability);
-       boot_cpu_data.x86 = (eax >> 8) & 0xf;
-       boot_cpu_data.x86_model = (eax >> 4) & 0xf;
-       boot_cpu_data.x86_mask = eax & 0xf;
 }
 
 void __init x86_64_start_kernel(char * real_mode_data)
 {
-       char *s;
        int i;
 
        for (i = 0; i < 256; i++)
@@ -84,10 +62,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
        asm volatile("lidt %0" :: "m" (idt_descr));
        clear_bss();
 
-       /*
-        * This must be called really, really early:
-        */
-       lockdep_init();
+       early_printk("Kernel alive\n");
 
        /*
         * switch to init_level4_pgt from boot_level4_pgt
@@ -103,22 +78,5 @@ void __init x86_64_start_kernel(char * real_mode_data)
 #ifdef CONFIG_SMP
        cpu_set(0, cpu_online_map);
 #endif
-       s = strstr(saved_command_line, "earlyprintk=");
-       if (s != NULL)
-               setup_early_printk(strchr(s, '=') + 1);
-#ifdef CONFIG_NUMA
-       s = strstr(saved_command_line, "numa=");
-       if (s != NULL)
-               numa_setup(s+5);
-#endif
-#ifdef CONFIG_X86_IO_APIC
-       if (strstr(saved_command_line, "disableapic"))
-               disable_apic = 1;
-#endif
-       /* You need early console to see that */
-       if (__pa_symbol(&_end) >= KERNEL_TEXT_SIZE)
-               panic("Kernel too big for kernel mapping\n");
-
-       setup_boot_cpu_data();
        start_kernel();
 }
index 0434b1f8e3dd47bbea3514aaee35c8a6cd56da40..2dd51f364ea2d62c7f779c1673a742fe839d6a71 100644 (file)
@@ -55,7 +55,6 @@
  */
 BUILD_16_IRQS(0x0)
 
-#ifdef CONFIG_X86_LOCAL_APIC
 /*
  * The IO-APIC gives us many more interrupt sources. Most of these 
  * are unused but an SMP system is supposed to have enough memory ...
@@ -75,8 +74,6 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
        BUILD_15_IRQS(0xe)
 #endif
 
-#endif
-
 #undef BUILD_16_IRQS
 #undef BUILD_15_IRQS
 #undef BI
@@ -100,7 +97,6 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
 void (*interrupt[NR_IRQS])(void) = {
        IRQLIST_16(0x0),
 
-#ifdef CONFIG_X86_IO_APIC
                         IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
        IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
        IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
@@ -110,7 +106,6 @@ void (*interrupt[NR_IRQS])(void) = {
        , IRQLIST_15(0xe)
 #endif
 
-#endif
 };
 
 #undef IRQ
@@ -128,6 +123,8 @@ void (*interrupt[NR_IRQS])(void) = {
 
 DEFINE_SPINLOCK(i8259A_lock);
 
+static int i8259A_auto_eoi;
+
 static void end_8259A_irq (unsigned int irq)
 {
        if (irq > 256) { 
@@ -341,6 +338,8 @@ void init_8259A(int auto_eoi)
 {
        unsigned long flags;
 
+       i8259A_auto_eoi = auto_eoi;
+
        spin_lock_irqsave(&i8259A_lock, flags);
 
        outb(0xff, 0x21);       /* mask all of 8259A-1 */
@@ -399,7 +398,7 @@ static void save_ELCR(char *trigger)
 
 static int i8259A_resume(struct sys_device *dev)
 {
-       init_8259A(0);
+       init_8259A(i8259A_auto_eoi);
        restore_ELCR(irq_trigger);
        return 0;
 }
@@ -453,9 +452,7 @@ void __init init_ISA_irqs (void)
 {
        int i;
 
-#ifdef CONFIG_X86_LOCAL_APIC
        init_bsp_APIC();
-#endif
        init_8259A(0);
 
        for (i = 0; i < NR_IRQS; i++) {
@@ -581,14 +578,12 @@ void __init init_IRQ(void)
        set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
        set_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
 
-#ifdef CONFIG_X86_LOCAL_APIC
        /* 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);
-#endif
 
        /*
         * Set the clock to HZ Hz, we already have a valid
index 924a4a332954349e56dd990efb82e037d18d0154..0491019d4c8dc44204995cab7bf5eee7b1973c31 100644 (file)
@@ -48,7 +48,7 @@ int sis_apic_bug; /* not actually supported, dummy for compile */
 
 static int no_timer_check;
 
-int disable_timer_pin_1 __initdata;
+static int disable_timer_pin_1 __initdata;
 
 int timer_over_8254 __initdata = 0;
 
@@ -111,6 +111,33 @@ int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
        FINAL;                                                          \
 }
 
+union entry_union {
+       struct { u32 w1, w2; };
+       struct IO_APIC_route_entry entry;
+};
+
+static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
+{
+       union entry_union eu;
+       unsigned long flags;
+       spin_lock_irqsave(&ioapic_lock, flags);
+       eu.w1 = io_apic_read(apic, 0x10 + 2 * pin);
+       eu.w2 = io_apic_read(apic, 0x11 + 2 * pin);
+       spin_unlock_irqrestore(&ioapic_lock, flags);
+       return eu.entry;
+}
+
+static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
+{
+       unsigned long flags;
+       union entry_union eu;
+       eu.entry = e;
+       spin_lock_irqsave(&ioapic_lock, flags);
+       io_apic_write(apic, 0x10 + 2*pin, eu.w1);
+       io_apic_write(apic, 0x11 + 2*pin, eu.w2);
+       spin_unlock_irqrestore(&ioapic_lock, flags);
+}
+
 #ifdef CONFIG_SMP
 static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
 {
@@ -196,13 +223,9 @@ static void unmask_IO_APIC_irq (unsigned int irq)
 static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
 {
        struct IO_APIC_route_entry entry;
-       unsigned long flags;
 
        /* Check delivery_mode to be sure we're not clearing an SMI pin */
-       spin_lock_irqsave(&ioapic_lock, flags);
-       *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
-       *(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       entry = ioapic_read_entry(apic, pin);
        if (entry.delivery_mode == dest_SMI)
                return;
        /*
@@ -210,10 +233,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
         */
        memset(&entry, 0, sizeof(entry));
        entry.mask = 1;
-       spin_lock_irqsave(&ioapic_lock, flags);
-       io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&entry) + 0));
-       io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&entry) + 1));
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       ioapic_write_entry(apic, pin, entry);
 }
 
 static void clear_IO_APIC (void)
@@ -225,14 +245,6 @@ static void clear_IO_APIC (void)
                        clear_IO_APIC_pin(apic, pin);
 }
 
-/*
- * support for broken MP BIOSs, enables hand-redirection of PIRQ0-7 to
- * specific CPU-side IRQs.
- */
-
-#define MAX_PIRQS 8
-static int pirq_entries [MAX_PIRQS];
-static int pirqs_enabled;
 int skip_ioapic_setup;
 int ioapic_force;
 
@@ -241,18 +253,17 @@ int ioapic_force;
 static int __init disable_ioapic_setup(char *str)
 {
        skip_ioapic_setup = 1;
-       return 1;
+       return 0;
 }
+early_param("noapic", disable_ioapic_setup);
 
-static int __init enable_ioapic_setup(char *str)
+/* Actually the next is obsolete, but keep it for paranoid reasons -AK */
+static int __init disable_timer_pin_setup(char *arg)
 {
-       ioapic_force = 1;
-       skip_ioapic_setup = 0;
+       disable_timer_pin_1 = 1;
        return 1;
 }
-
-__setup("noapic", disable_ioapic_setup);
-__setup("apic", enable_ioapic_setup);
+__setup("disable_timer_pin_1", disable_timer_pin_setup);
 
 static int __init setup_disable_8254_timer(char *s)
 {
@@ -268,135 +279,6 @@ static int __init setup_enable_8254_timer(char *s)
 __setup("disable_8254_timer", setup_disable_8254_timer);
 __setup("enable_8254_timer", setup_enable_8254_timer);
 
-#include <asm/pci-direct.h>
-#include <linux/pci_ids.h>
-#include <linux/pci.h>
-
-
-#ifdef CONFIG_ACPI
-
-static int nvidia_hpet_detected __initdata;
-
-static int __init nvidia_hpet_check(unsigned long phys, unsigned long size)
-{
-       nvidia_hpet_detected = 1;
-       return 0;
-}
-#endif
-
-/* Temporary Hack. Nvidia and VIA boards currently only work with IO-APIC
-   off. Check for an Nvidia or VIA PCI bridge and turn it off.
-   Use pci direct infrastructure because this runs before the PCI subsystem. 
-
-   Can be overwritten with "apic"
-
-   And another hack to disable the IOMMU on VIA chipsets.
-
-   ... and others. Really should move this somewhere else.
-
-   Kludge-O-Rama. */
-void __init check_ioapic(void) 
-{ 
-       int num,slot,func; 
-       /* Poor man's PCI discovery */
-       for (num = 0; num < 32; num++) { 
-               for (slot = 0; slot < 32; slot++) { 
-                       for (func = 0; func < 8; func++) { 
-                               u32 class;
-                               u32 vendor;
-                               u8 type;
-                               class = read_pci_config(num,slot,func,
-                                                       PCI_CLASS_REVISION);
-                               if (class == 0xffffffff)
-                                       break; 
-
-                               if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
-                                       continue; 
-
-                               vendor = read_pci_config(num, slot, func, 
-                                                        PCI_VENDOR_ID);
-                               vendor &= 0xffff;
-                               switch (vendor) { 
-                               case PCI_VENDOR_ID_VIA:
-#ifdef CONFIG_IOMMU
-                                       if ((end_pfn > MAX_DMA32_PFN ||
-                                            force_iommu) &&
-                                           !iommu_aperture_allowed) {
-                                               printk(KERN_INFO
-    "Looks like a VIA chipset. Disabling IOMMU. Override with \"iommu=allowed\"\n");
-                                               iommu_aperture_disabled = 1;
-                                       }
-#endif
-                                       return;
-                               case PCI_VENDOR_ID_NVIDIA:
-#ifdef CONFIG_ACPI
-                                       /*
-                                        * All timer overrides on Nvidia are
-                                        * wrong unless HPET is enabled.
-                                        */
-                                       nvidia_hpet_detected = 0;
-                                       acpi_table_parse(ACPI_HPET,
-                                                       nvidia_hpet_check);
-                                       if (nvidia_hpet_detected == 0) {
-                                               acpi_skip_timer_override = 1;
-                                               printk(KERN_INFO "Nvidia board "
-                                                   "detected. Ignoring ACPI "
-                                                   "timer override.\n");
-                                       }
-#endif
-                                       /* RED-PEN skip them on mptables too? */
-                                       return;
-
-                               /* This should be actually default, but
-                                  for 2.6.16 let's do it for ATI only where
-                                  it's really needed. */
-                               case PCI_VENDOR_ID_ATI:
-                                       if (timer_over_8254 == 1) {     
-                                               timer_over_8254 = 0;    
-                                       printk(KERN_INFO
-               "ATI board detected. Disabling timer routing over 8254.\n");
-                                       }       
-                                       return;
-                               } 
-
-
-                               /* No multi-function device? */
-                               type = read_pci_config_byte(num,slot,func,
-                                                           PCI_HEADER_TYPE);
-                               if (!(type & 0x80))
-                                       break;
-                       } 
-               }
-       }
-} 
-
-static int __init ioapic_pirq_setup(char *str)
-{
-       int i, max;
-       int ints[MAX_PIRQS+1];
-
-       get_options(str, ARRAY_SIZE(ints), ints);
-
-       for (i = 0; i < MAX_PIRQS; i++)
-               pirq_entries[i] = -1;
-
-       pirqs_enabled = 1;
-       apic_printk(APIC_VERBOSE, "PIRQ redirection, working around broken MP-BIOS.\n");
-       max = MAX_PIRQS;
-       if (ints[0] < MAX_PIRQS)
-               max = ints[0];
-
-       for (i = 0; i < max; i++) {
-               apic_printk(APIC_VERBOSE, "... PIRQ%d -> IRQ %d\n", i, ints[i+1]);
-               /*
-                * PIRQs are mapped upside down, usually.
-                */
-               pirq_entries[MAX_PIRQS-i-1] = ints[i+1];
-       }
-       return 1;
-}
-
-__setup("pirq=", ioapic_pirq_setup);
 
 /*
  * Find the IRQ entry number of a certain pin.
@@ -425,9 +307,7 @@ static int __init find_isa_irq_pin(int irq, int type)
        for (i = 0; i < mp_irq_entries; i++) {
                int lbus = mp_irqs[i].mpc_srcbus;
 
-               if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
-                    mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
-                    mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
+               if (test_bit(lbus, mp_bus_not_pci) &&
                    (mp_irqs[i].mpc_irqtype == type) &&
                    (mp_irqs[i].mpc_srcbusirq == irq))
 
@@ -443,9 +323,7 @@ static int __init find_isa_irq_apic(int irq, int type)
        for (i = 0; i < mp_irq_entries; i++) {
                int lbus = mp_irqs[i].mpc_srcbus;
 
-               if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
-                    mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
-                    mp_bus_id_to_type[lbus] == MP_BUS_MCA) &&
+               if (test_bit(lbus, mp_bus_not_pci) &&
                    (mp_irqs[i].mpc_irqtype == type) &&
                    (mp_irqs[i].mpc_srcbusirq == irq))
                        break;
@@ -485,7 +363,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
                            mp_irqs[i].mpc_dstapic == MP_APIC_ALL)
                                break;
 
-               if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
+               if (!test_bit(lbus, mp_bus_not_pci) &&
                    !mp_irqs[i].mpc_irqtype &&
                    (bus == lbus) &&
                    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
@@ -508,27 +386,6 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
        return best_guess;
 }
 
-/*
- * EISA Edge/Level control register, ELCR
- */
-static int EISA_ELCR(unsigned int irq)
-{
-       if (irq < 16) {
-               unsigned int port = 0x4d0 + (irq >> 3);
-               return (inb(port) >> (irq & 7)) & 1;
-       }
-       apic_printk(APIC_VERBOSE, "Broken MPtable reports ISA irq %d\n", irq);
-       return 0;
-}
-
-/* EISA interrupts are always polarity zero and can be edge or level
- * trigger depending on the ELCR value.  If an interrupt is listed as
- * EISA conforming in the MP table, that means its trigger type must
- * be read in from the ELCR */
-
-#define default_EISA_trigger(idx)      (EISA_ELCR(mp_irqs[idx].mpc_srcbusirq))
-#define default_EISA_polarity(idx)     (0)
-
 /* ISA interrupts are always polarity zero edge triggered,
  * when listed as conforming in the MP table. */
 
@@ -541,12 +398,6 @@ static int EISA_ELCR(unsigned int irq)
 #define default_PCI_trigger(idx)       (1)
 #define default_PCI_polarity(idx)      (1)
 
-/* MCA interrupts are always polarity zero level triggered,
- * when listed as conforming in the MP table. */
-
-#define default_MCA_trigger(idx)       (1)
-#define default_MCA_polarity(idx)      (0)
-
 static int __init MPBIOS_polarity(int idx)
 {
        int bus = mp_irqs[idx].mpc_srcbus;
@@ -558,38 +409,11 @@ static int __init MPBIOS_polarity(int idx)
        switch (mp_irqs[idx].mpc_irqflag & 3)
        {
                case 0: /* conforms, ie. bus-type dependent polarity */
-               {
-                       switch (mp_bus_id_to_type[bus])
-                       {
-                               case MP_BUS_ISA: /* ISA pin */
-                               {
-                                       polarity = default_ISA_polarity(idx);
-                                       break;
-                               }
-                               case MP_BUS_EISA: /* EISA pin */
-                               {
-                                       polarity = default_EISA_polarity(idx);
-                                       break;
-                               }
-                               case MP_BUS_PCI: /* PCI pin */
-                               {
-                                       polarity = default_PCI_polarity(idx);
-                                       break;
-                               }
-                               case MP_BUS_MCA: /* MCA pin */
-                               {
-                                       polarity = default_MCA_polarity(idx);
-                                       break;
-                               }
-                               default:
-                               {
-                                       printk(KERN_WARNING "broken BIOS!!\n");
-                                       polarity = 1;
-                                       break;
-                               }
-                       }
+                       if (test_bit(bus, mp_bus_not_pci))
+                               polarity = default_ISA_polarity(idx);
+                       else
+                               polarity = default_PCI_polarity(idx);
                        break;
-               }
                case 1: /* high active */
                {
                        polarity = 0;
@@ -627,38 +451,11 @@ static int MPBIOS_trigger(int idx)
        switch ((mp_irqs[idx].mpc_irqflag>>2) & 3)
        {
                case 0: /* conforms, ie. bus-type dependent */
-               {
-                       switch (mp_bus_id_to_type[bus])
-                       {
-                               case MP_BUS_ISA: /* ISA pin */
-                               {
-                                       trigger = default_ISA_trigger(idx);
-                                       break;
-                               }
-                               case MP_BUS_EISA: /* EISA pin */
-                               {
-                                       trigger = default_EISA_trigger(idx);
-                                       break;
-                               }
-                               case MP_BUS_PCI: /* PCI pin */
-                               {
-                                       trigger = default_PCI_trigger(idx);
-                                       break;
-                               }
-                               case MP_BUS_MCA: /* MCA pin */
-                               {
-                                       trigger = default_MCA_trigger(idx);
-                                       break;
-                               }
-                               default:
-                               {
-                                       printk(KERN_WARNING "broken BIOS!!\n");
-                                       trigger = 1;
-                                       break;
-                               }
-                       }
+                       if (test_bit(bus, mp_bus_not_pci))
+                               trigger = default_ISA_trigger(idx);
+                       else
+                               trigger = default_PCI_trigger(idx);
                        break;
-               }
                case 1: /* edge */
                {
                        trigger = 0;
@@ -764,49 +561,17 @@ static int pin_2_irq(int idx, int apic, int pin)
        if (mp_irqs[idx].mpc_dstirq != pin)
                printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
 
-       switch (mp_bus_id_to_type[bus])
-       {
-               case MP_BUS_ISA: /* ISA pin */
-               case MP_BUS_EISA:
-               case MP_BUS_MCA:
-               {
-                       irq = mp_irqs[idx].mpc_srcbusirq;
-                       break;
-               }
-               case MP_BUS_PCI: /* PCI pin */
-               {
-                       /*
-                        * PCI IRQs are mapped in order
-                        */
-                       i = irq = 0;
-                       while (i < apic)
-                               irq += nr_ioapic_registers[i++];
-                       irq += pin;
-                       irq = gsi_irq_sharing(irq);
-                       break;
-               }
-               default:
-               {
-                       printk(KERN_ERR "unknown bus type %d.\n",bus); 
-                       irq = 0;
-                       break;
-               }
-       }
-       BUG_ON(irq >= NR_IRQS);
-
-       /*
-        * PCI IRQ command line redirection. Yes, limits are hardcoded.
-        */
-       if ((pin >= 16) && (pin <= 23)) {
-               if (pirq_entries[pin-16] != -1) {
-                       if (!pirq_entries[pin-16]) {
-                               apic_printk(APIC_VERBOSE, "disabling PIRQ%d\n", pin-16);
-                       } else {
-                               irq = pirq_entries[pin-16];
-                               apic_printk(APIC_VERBOSE, "using PIRQ%d -> IRQ %d\n",
-                                               pin-16, irq);
-                       }
-               }
+       if (test_bit(bus, mp_bus_not_pci)) {
+               irq = mp_irqs[idx].mpc_srcbusirq;
+       } else {
+               /*
+                * PCI IRQs are mapped in order
+                */
+               i = irq = 0;
+               while (i < apic)
+                       irq += nr_ioapic_registers[i++];
+               irq += pin;
+               irq = gsi_irq_sharing(irq);
        }
        BUG_ON(irq >= NR_IRQS);
        return irq;
@@ -943,9 +708,9 @@ static void __init setup_IO_APIC_irqs(void)
                        if (!apic && (irq < 16))
                                disable_8259A_irq(irq);
                }
+               ioapic_write_entry(apic, pin, entry);
+
                spin_lock_irqsave(&ioapic_lock, flags);
-               io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
-               io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
                set_native_irq_info(irq, TARGET_CPUS);
                spin_unlock_irqrestore(&ioapic_lock, flags);
        }
@@ -1083,10 +848,7 @@ void __apicdebuginit print_IO_APIC(void)
        for (i = 0; i <= reg_01.bits.entries; i++) {
                struct IO_APIC_route_entry entry;
 
-               spin_lock_irqsave(&ioapic_lock, flags);
-               *(((int *)&entry)+0) = io_apic_read(apic, 0x10+i*2);
-               *(((int *)&entry)+1) = io_apic_read(apic, 0x11+i*2);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
+               entry = ioapic_read_entry(apic, i);
 
                printk(KERN_DEBUG " %02x %03X %02X  ",
                        i,
@@ -1281,9 +1043,6 @@ static void __init enable_IO_APIC(void)
                irq_2_pin[i].pin = -1;
                irq_2_pin[i].next = 0;
        }
-       if (!pirqs_enabled)
-               for (i = 0; i < MAX_PIRQS; i++)
-                       pirq_entries[i] = -1;
 
        /*
         * The number of IO-APIC IRQ registers (== #pins):
@@ -1299,11 +1058,7 @@ static void __init enable_IO_APIC(void)
                /* See if any of the pins is in ExtINT mode */
                for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
                        struct IO_APIC_route_entry entry;
-                       spin_lock_irqsave(&ioapic_lock, flags);
-                       *(((int *)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin);
-                       *(((int *)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin);
-                       spin_unlock_irqrestore(&ioapic_lock, flags);
-
+                       entry = ioapic_read_entry(apic, pin);
 
                        /* If the interrupt line is enabled and in ExtInt mode
                         * I have found the pin where the i8259 is connected.
@@ -1355,7 +1110,6 @@ void disable_IO_APIC(void)
         */
        if (ioapic_i8259.pin != -1) {
                struct IO_APIC_route_entry entry;
-               unsigned long flags;
 
                memset(&entry, 0, sizeof(entry));
                entry.mask            = 0; /* Enabled */
@@ -1372,83 +1126,12 @@ void disable_IO_APIC(void)
                /*
                 * Add it to the IO-APIC irq-routing table:
                 */
-               spin_lock_irqsave(&ioapic_lock, flags);
-               io_apic_write(ioapic_i8259.apic, 0x11+2*ioapic_i8259.pin,
-                       *(((int *)&entry)+1));
-               io_apic_write(ioapic_i8259.apic, 0x10+2*ioapic_i8259.pin,
-                       *(((int *)&entry)+0));
-               spin_unlock_irqrestore(&ioapic_lock, flags);
+               ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
        }
 
        disconnect_bsp_APIC(ioapic_i8259.pin != -1);
 }
 
-/*
- * function to set the IO-APIC physical IDs based on the
- * values stored in the MPC table.
- *
- * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
- */
-
-static void __init setup_ioapic_ids_from_mpc (void)
-{
-       union IO_APIC_reg_00 reg_00;
-       int apic;
-       int i;
-       unsigned char old_id;
-       unsigned long flags;
-
-       /*
-        * Set the IOAPIC ID to the value stored in the MPC table.
-        */
-       for (apic = 0; apic < nr_ioapics; apic++) {
-
-               /* Read the register 0 value */
-               spin_lock_irqsave(&ioapic_lock, flags);
-               reg_00.raw = io_apic_read(apic, 0);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
-               
-               old_id = mp_ioapics[apic].mpc_apicid;
-
-
-               printk(KERN_INFO "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid);
-
-
-               /*
-                * We need to adjust the IRQ routing table
-                * if the ID changed.
-                */
-               if (old_id != mp_ioapics[apic].mpc_apicid)
-                       for (i = 0; i < mp_irq_entries; i++)
-                               if (mp_irqs[i].mpc_dstapic == old_id)
-                                       mp_irqs[i].mpc_dstapic
-                                               = mp_ioapics[apic].mpc_apicid;
-
-               /*
-                * Read the right value from the MPC table and
-                * write it into the ID register.
-                */
-               apic_printk(APIC_VERBOSE,KERN_INFO "...changing IO-APIC physical APIC ID to %d ...",
-                               mp_ioapics[apic].mpc_apicid);
-
-               reg_00.bits.ID = mp_ioapics[apic].mpc_apicid;
-               spin_lock_irqsave(&ioapic_lock, flags);
-               io_apic_write(apic, 0, reg_00.raw);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
-
-               /*
-                * Sanity check
-                */
-               spin_lock_irqsave(&ioapic_lock, flags);
-               reg_00.raw = io_apic_read(apic, 0);
-               spin_unlock_irqrestore(&ioapic_lock, flags);
-               if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid)
-                       printk("could not set ID!\n");
-               else
-                       apic_printk(APIC_VERBOSE," ok.\n");
-       }
-}
-
 /*
  * There is a nasty bug in some older SMP boards, their mptable lies
  * about the timer IRQ. We do the following to work around the situation:
@@ -1964,11 +1647,6 @@ void __init setup_IO_APIC(void)
 
        apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
 
-       /*
-        * Set up the IO-APIC IRQ routing table.
-        */
-       if (!acpi_ioapic)
-               setup_ioapic_ids_from_mpc();
        sync_Arb_IDs();
        setup_IO_APIC_irqs();
        init_IO_APIC_traps();
@@ -1987,17 +1665,12 @@ static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
 {
        struct IO_APIC_route_entry *entry;
        struct sysfs_ioapic_data *data;
-       unsigned long flags;
        int i;
 
        data = container_of(dev, struct sysfs_ioapic_data, dev);
        entry = data->entry;
-       spin_lock_irqsave(&ioapic_lock, flags);
-       for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
-               *(((int *)entry) + 1) = io_apic_read(dev->id, 0x11 + 2 * i);
-               *(((int *)entry) + 0) = io_apic_read(dev->id, 0x10 + 2 * i);
-       }
-       spin_unlock_irqrestore(&ioapic_lock, flags);
+       for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ )
+               *entry = ioapic_read_entry(dev->id, i);
 
        return 0;
 }
@@ -2019,11 +1692,9 @@ static int ioapic_resume(struct sys_device *dev)
                reg_00.bits.ID = mp_ioapics[dev->id].mpc_apicid;
                io_apic_write(dev->id, 0, reg_00.raw);
        }
-       for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ ) {
-               io_apic_write(dev->id, 0x11+2*i, *(((int *)entry)+1));
-               io_apic_write(dev->id, 0x10+2*i, *(((int *)entry)+0));
-       }
        spin_unlock_irqrestore(&ioapic_lock, flags);
+       for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
+               ioapic_write_entry(dev->id, i, entry[i]);
 
        return 0;
 }
@@ -2077,19 +1748,6 @@ device_initcall(ioapic_init_sysfs);
 
 #define IO_APIC_MAX_ID         0xFE
 
-int __init io_apic_get_version (int ioapic)
-{
-       union IO_APIC_reg_01    reg_01;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ioapic_lock, flags);
-       reg_01.raw = io_apic_read(ioapic, 1);
-       spin_unlock_irqrestore(&ioapic_lock, flags);
-
-       return reg_01.bits.version;
-}
-
-
 int __init io_apic_get_redir_entries (int ioapic)
 {
        union IO_APIC_reg_01    reg_01;
@@ -2148,10 +1806,10 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p
        if (!ioapic && (irq < 16))
                disable_8259A_irq(irq);
 
+       ioapic_write_entry(ioapic, pin, entry);
+
        spin_lock_irqsave(&ioapic_lock, flags);
-       io_apic_write(ioapic, 0x11+2*pin, *(((int *)&entry)+1));
-       io_apic_write(ioapic, 0x10+2*pin, *(((int *)&entry)+0));
-       set_native_irq_info(use_pci_vector() ?  entry.vector : irq, TARGET_CPUS);
+       set_native_irq_info(use_pci_vector() ? entry.vector : irq, TARGET_CPUS);
        spin_unlock_irqrestore(&ioapic_lock, flags);
 
        return 0;
index b81614970ecce60315ab9ea10c65c9d4562f253f..fe063d3cfe42b7ff8c09184cd6986492cce01eeb 100644 (file)
@@ -56,6 +56,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 
                memset(bitmap, 0xff, IO_BITMAP_BYTES);
                t->io_bitmap_ptr = bitmap;
+               set_thread_flag(TIF_IO_BITMAP);
        }
 
        /*
index 5221a53e90c1e0b7d68d126c6a31fef19abff6db..b3677e6ccc6ed8a2fbef0c4bdfc51041d25918be 100644 (file)
 #include <asm/idle.h>
 
 atomic_t irq_err_count;
-#ifdef CONFIG_X86_IO_APIC
-#ifdef APIC_MISMATCH_DEBUG
-atomic_t irq_mis_count;
-#endif
-#endif
 
 #ifdef CONFIG_DEBUG_STACKOVERFLOW
 /*
@@ -92,18 +87,11 @@ skip:
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
                seq_putc(p, '\n');
-#ifdef CONFIG_X86_LOCAL_APIC
                seq_printf(p, "LOC: ");
                for_each_online_cpu(j)
                        seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs);
                seq_putc(p, '\n');
-#endif
                seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
-#ifdef CONFIG_X86_IO_APIC
-#ifdef APIC_MISMATCH_DEBUG
-               seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
-#endif
-#endif
        }
        return 0;
 }
index 106076b370fc8fa8a4cfc2faf610bf237b2dbde0..0497e3bd5bfff8718547a1a270d3ee36d59c74c1 100644 (file)
 #include <asm/mmu_context.h>
 #include <asm/io.h>
 
+#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
+static u64 kexec_pgd[512] PAGE_ALIGNED;
+static u64 kexec_pud0[512] PAGE_ALIGNED;
+static u64 kexec_pmd0[512] PAGE_ALIGNED;
+static u64 kexec_pte0[512] PAGE_ALIGNED;
+static u64 kexec_pud1[512] PAGE_ALIGNED;
+static u64 kexec_pmd1[512] PAGE_ALIGNED;
+static u64 kexec_pte1[512] PAGE_ALIGNED;
+
 static void init_level2_page(pmd_t *level2p, unsigned long addr)
 {
        unsigned long end_addr;
@@ -144,32 +153,19 @@ static void load_segments(void)
                );
 }
 
-typedef NORET_TYPE void (*relocate_new_kernel_t)(unsigned long indirection_page,
-                                       unsigned long control_code_buffer,
-                                       unsigned long start_address,
-                                       unsigned long pgtable) ATTRIB_NORET;
-
-extern const unsigned char relocate_new_kernel[];
-extern const unsigned long relocate_new_kernel_size;
-
 int machine_kexec_prepare(struct kimage *image)
 {
-       unsigned long start_pgtable, control_code_buffer;
+       unsigned long start_pgtable;
        int result;
 
        /* Calculate the offsets */
        start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
-       control_code_buffer = start_pgtable + PAGE_SIZE;
 
        /* Setup the identity mapped 64bit page table */
        result = init_pgtable(image, start_pgtable);
        if (result)
                return result;
 
-       /* Place the code in the reboot code buffer */
-       memcpy(__va(control_code_buffer), relocate_new_kernel,
-                                               relocate_new_kernel_size);
-
        return 0;
 }
 
@@ -184,28 +180,34 @@ void machine_kexec_cleanup(struct kimage *image)
  */
 NORET_TYPE void machine_kexec(struct kimage *image)
 {
-       unsigned long page_list;
-       unsigned long control_code_buffer;
-       unsigned long start_pgtable;
-       relocate_new_kernel_t rnk;
+       unsigned long page_list[PAGES_NR];
+       void *control_page;
 
        /* Interrupts aren't acceptable while we reboot */
        local_irq_disable();
 
-       /* Calculate the offsets */
-       page_list = image->head;
-       start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
-       control_code_buffer = start_pgtable + PAGE_SIZE;
-
-       /* Set the low half of the page table to my identity mapped
-        * page table for kexec.  Leave the high half pointing at the
-        * kernel pages.   Don't bother to flush the global pages
-        * as that will happen when I fully switch to my identity mapped
-        * page table anyway.
-        */
-       memcpy(__va(read_cr3()), __va(start_pgtable), PAGE_SIZE/2);
-       __flush_tlb();
-
+       control_page = page_address(image->control_code_page) + PAGE_SIZE;
+       memcpy(control_page, relocate_kernel, PAGE_SIZE);
+
+       page_list[PA_CONTROL_PAGE] = __pa(control_page);
+       page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel;
+       page_list[PA_PGD] = __pa(kexec_pgd);
+       page_list[VA_PGD] = (unsigned long)kexec_pgd;
+       page_list[PA_PUD_0] = __pa(kexec_pud0);
+       page_list[VA_PUD_0] = (unsigned long)kexec_pud0;
+       page_list[PA_PMD_0] = __pa(kexec_pmd0);
+       page_list[VA_PMD_0] = (unsigned long)kexec_pmd0;
+       page_list[PA_PTE_0] = __pa(kexec_pte0);
+       page_list[VA_PTE_0] = (unsigned long)kexec_pte0;
+       page_list[PA_PUD_1] = __pa(kexec_pud1);
+       page_list[VA_PUD_1] = (unsigned long)kexec_pud1;
+       page_list[PA_PMD_1] = __pa(kexec_pmd1);
+       page_list[VA_PMD_1] = (unsigned long)kexec_pmd1;
+       page_list[PA_PTE_1] = __pa(kexec_pte1);
+       page_list[VA_PTE_1] = (unsigned long)kexec_pte1;
+
+       page_list[PA_TABLE_PAGE] =
+         (unsigned long)__pa(page_address(image->control_code_page));
 
        /* The segment registers are funny things, they have both a
         * visible and an invisible part.  Whenever the visible part is
@@ -222,7 +224,36 @@ NORET_TYPE void machine_kexec(struct kimage *image)
         */
        set_gdt(phys_to_virt(0),0);
        set_idt(phys_to_virt(0),0);
+
        /* now call it */
-       rnk = (relocate_new_kernel_t) control_code_buffer;
-       (*rnk)(page_list, control_code_buffer, image->start, start_pgtable);
+       relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
+                       image->start);
 }
+
+/* crashkernel=size@addr specifies the location to reserve for
+ * a crash kernel.  By reserving this memory we guarantee
+ * that linux never set's it up as a DMA target.
+ * Useful for holding code to do something appropriate
+ * after a kernel panic.
+ */
+static int __init setup_crashkernel(char *arg)
+{
+       unsigned long size, base;
+       char *p;
+       if (!arg)
+               return -EINVAL;
+       size = memparse(arg, &p);
+       if (arg == p)
+               return -EINVAL;
+       if (*p == '@') {
+               base = memparse(p+1, &p);
+               /* FIXME: Do I want a sanity check to validate the
+                * memory range?  Yes you do, but it's too early for
+                * e820 -AK */
+               crashk_res.start = base;
+               crashk_res.end   = base + size - 1;
+       }
+       return 0;
+}
+early_param("crashkernel", setup_crashkernel);
+
index 4e017fb30fb3f60c824fabc384bd895867dc90e8..bbea88801d883cc8928c6a9c91fe5bf5efbf4c9f 100644 (file)
@@ -182,7 +182,7 @@ void do_machine_check(struct pt_regs * regs, long error_code)
                goto out2;
 
        memset(&m, 0, sizeof(struct mce));
-       m.cpu = safe_smp_processor_id();
+       m.cpu = smp_processor_id();
        rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus);
        if (!(m.mcgstatus & MCG_STATUS_RIPV))
                kill_it = 1;
@@ -274,6 +274,33 @@ void do_machine_check(struct pt_regs * regs, long error_code)
        atomic_dec(&mce_entry);
 }
 
+#ifdef CONFIG_X86_MCE_INTEL
+/***
+ * mce_log_therm_throt_event - Logs the thermal throttling event to mcelog
+ * @cpu: The CPU on which the event occured.
+ * @status: Event status information
+ *
+ * This function should be called by the thermal interrupt after the
+ * event has been processed and the decision was made to log the event
+ * further.
+ *
+ * The status parameter will be saved to the 'status' field of 'struct mce'
+ * and historically has been the register value of the
+ * MSR_IA32_THERMAL_STATUS (Intel) msr.
+ */
+void mce_log_therm_throt_event(unsigned int cpu, __u64 status)
+{
+       struct mce m;
+
+       memset(&m, 0, sizeof(m));
+       m.cpu = cpu;
+       m.bank = MCE_THERMAL_BANK;
+       m.status = status;
+       rdtscll(m.tsc);
+       mce_log(&m);
+}
+#endif /* CONFIG_X86_MCE_INTEL */
+
 /*
  * Periodic polling timer for "silent" machine check errors.
  */
index 8f533d2c40cbdf3e25114206ee85c5362eec74c1..6551505d8a2cd8d0c7276d32334bef0b1aed0809 100644 (file)
 #include <asm/mce.h>
 #include <asm/hw_irq.h>
 #include <asm/idle.h>
-
-static DEFINE_PER_CPU(unsigned long, next_check);
+#include <asm/therm_throt.h>
 
 asmlinkage void smp_thermal_interrupt(void)
 {
-       struct mce m;
+       __u64 msr_val;
 
        ack_APIC_irq();
 
        exit_idle();
        irq_enter();
-       if (time_before(jiffies, __get_cpu_var(next_check)))
-               goto done;
-
-       __get_cpu_var(next_check) = jiffies + HZ*300;
-       memset(&m, 0, sizeof(m));
-       m.cpu = smp_processor_id();
-       m.bank = MCE_THERMAL_BANK;
-       rdtscll(m.tsc);
-       rdmsrl(MSR_IA32_THERM_STATUS, m.status);
-       if (m.status & 0x1) {
-               printk(KERN_EMERG
-                       "CPU%d: Temperature above threshold, cpu clock throttled\n", m.cpu);
-               add_taint(TAINT_MACHINE_CHECK);
-       } else {
-               printk(KERN_EMERG "CPU%d: Temperature/speed normal\n", m.cpu);
-       }
 
-       mce_log(&m);
-done:
+       rdmsrl(MSR_IA32_THERM_STATUS, msr_val);
+       if (therm_throt_process(msr_val & 1))
+               mce_log_therm_throt_event(smp_processor_id(), msr_val);
+
        irq_exit();
 }
 
@@ -92,6 +77,9 @@ static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
        apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
        printk(KERN_INFO "CPU%d: Thermal monitoring enabled (%s)\n",
                cpu, tm2 ? "TM2" : "TM1");
+
+       /* enable thermal throttle processing */
+       atomic_set(&therm_throt_en, 1);
        return;
 }
 
index a1ab4197f8a11594e59c57b20c67d5a6511c6cfa..20e88f4b564b6d8c31604c8c5c50f71da6a7ac0e 100644 (file)
@@ -41,8 +41,7 @@ int acpi_found_madt;
  * Various Linux-internal data structures created from the
  * MP-table.
  */
-unsigned char apic_version [MAX_APICS];
-unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
+DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
 
 static int mp_current_pci_id = 0;
@@ -56,7 +55,6 @@ struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
 int mp_irq_entries;
 
 int nr_ioapics;
-int pic_mode;
 unsigned long mp_lapic_addr = 0;
 
 
@@ -71,19 +69,6 @@ unsigned disabled_cpus __initdata;
 /* Bitmask of physically existing CPUs */
 physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
 
-/* ACPI MADT entry parsing functions */
-#ifdef CONFIG_ACPI
-extern struct acpi_boot_flags acpi_boot;
-#ifdef CONFIG_X86_LOCAL_APIC
-extern int acpi_parse_lapic (acpi_table_entry_header *header);
-extern int acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header);
-extern int acpi_parse_lapic_nmi (acpi_table_entry_header *header);
-#endif /*CONFIG_X86_LOCAL_APIC*/
-#ifdef CONFIG_X86_IO_APIC
-extern int acpi_parse_ioapic (acpi_table_entry_header *header);
-#endif /*CONFIG_X86_IO_APIC*/
-#endif /*CONFIG_ACPI*/
-
 u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
 
 
@@ -108,24 +93,20 @@ static int __init mpf_checksum(unsigned char *mp, int len)
 static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
 {
        int cpu;
-       unsigned char ver;
        cpumask_t tmp_map;
+       char *bootup_cpu = "";
 
        if (!(m->mpc_cpuflag & CPU_ENABLED)) {
                disabled_cpus++;
                return;
        }
-
-       printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n",
-               m->mpc_apicid,
-              (m->mpc_cpufeature & CPU_FAMILY_MASK)>>8,
-              (m->mpc_cpufeature & CPU_MODEL_MASK)>>4,
-               m->mpc_apicver);
-
        if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
-               Dprintk("    Bootup CPU\n");
+               bootup_cpu = " (Bootup-CPU)";
                boot_cpu_id = m->mpc_apicid;
        }
+
+       printk(KERN_INFO "Processor #%d%s\n", m->mpc_apicid, bootup_cpu);
+
        if (num_processors >= NR_CPUS) {
                printk(KERN_WARNING "WARNING: NR_CPUS limit of %i reached."
                        " Processor ignored.\n", NR_CPUS);
@@ -136,24 +117,7 @@ static void __cpuinit MP_processor_info (struct mpc_config_processor *m)
        cpus_complement(tmp_map, cpu_present_map);
        cpu = first_cpu(tmp_map);
 
-#if MAX_APICS < 255    
-       if ((int)m->mpc_apicid > MAX_APICS) {
-               printk(KERN_ERR "Processor #%d INVALID. (Max ID: %d).\n",
-                       m->mpc_apicid, MAX_APICS);
-               return;
-       }
-#endif
-       ver = m->mpc_apicver;
-
        physid_set(m->mpc_apicid, phys_cpu_present_map);
-       /*
-        * Validate version
-        */
-       if (ver == 0x0) {
-               printk(KERN_ERR "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
-               ver = 0x10;
-       }
-       apic_version[m->mpc_apicid] = ver;
        if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
                /*
                 * bios_cpu_apicid is required to have processors listed
@@ -178,15 +142,11 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
        Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
 
        if (strncmp(str, "ISA", 3) == 0) {
-               mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
-       } else if (strncmp(str, "EISA", 4) == 0) {
-               mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
+               set_bit(m->mpc_busid, mp_bus_not_pci);
        } else if (strncmp(str, "PCI", 3) == 0) {
-               mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
+               clear_bit(m->mpc_busid, mp_bus_not_pci);
                mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
                mp_current_pci_id++;
-       } else if (strncmp(str, "MCA", 3) == 0) {
-               mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
        } else {
                printk(KERN_ERR "Unknown bustype %s\n", str);
        }
@@ -197,8 +157,8 @@ static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
        if (!(m->mpc_flags & MPC_APIC_USABLE))
                return;
 
-       printk("I/O APIC #%d Version %d at 0x%X.\n",
-               m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
+       printk("I/O APIC #%d at 0x%X.\n",
+               m->mpc_apicid, m->mpc_apicaddr);
        if (nr_ioapics >= MAX_IO_APICS) {
                printk(KERN_ERR "Max # of I/O APICs (%d) exceeded (found %d).\n",
                        MAX_IO_APICS, nr_ioapics);
@@ -232,19 +192,6 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
                        m->mpc_irqtype, m->mpc_irqflag & 3,
                        (m->mpc_irqflag >> 2) &3, m->mpc_srcbusid,
                        m->mpc_srcbusirq, m->mpc_destapic, m->mpc_destapiclint);
-       /*
-        * Well it seems all SMP boards in existence
-        * use ExtINT/LVT1 == LINT0 and
-        * NMI/LVT2 == LINT1 - the following check
-        * will show us if this assumptions is false.
-        * Until then we do not have to add baggage.
-        */
-       if ((m->mpc_irqtype == mp_ExtINT) &&
-               (m->mpc_destapiclint != 0))
-                       BUG();
-       if ((m->mpc_irqtype == mp_NMI) &&
-               (m->mpc_destapiclint != 1))
-                       BUG();
 }
 
 /*
@@ -258,7 +205,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
        unsigned char *mpt=((unsigned char *)mpc)+count;
 
        if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) {
-               printk("SMP mptable: bad signature [%c%c%c%c]!\n",
+               printk("MPTABLE: bad signature [%c%c%c%c]!\n",
                        mpc->mpc_signature[0],
                        mpc->mpc_signature[1],
                        mpc->mpc_signature[2],
@@ -266,31 +213,31 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
                return 0;
        }
        if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) {
-               printk("SMP mptable: checksum error!\n");
+               printk("MPTABLE: checksum error!\n");
                return 0;
        }
        if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) {
-               printk(KERN_ERR "SMP mptable: bad table version (%d)!!\n",
+               printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
                        mpc->mpc_spec);
                return 0;
        }
        if (!mpc->mpc_lapic) {
-               printk(KERN_ERR "SMP mptable: null local APIC address!\n");
+               printk(KERN_ERR "MPTABLE: null local APIC address!\n");
                return 0;
        }
        memcpy(str,mpc->mpc_oem,8);
-       str[8]=0;
-       printk(KERN_INFO "OEM ID: %s ",str);
+       str[8] = 0;
+       printk(KERN_INFO "MPTABLE: OEM ID: %s ",str);
 
        memcpy(str,mpc->mpc_productid,12);
-       str[12]=0;
-       printk("Product ID: %s ",str);
+       str[12] = 0;
+       printk("MPTABLE: Product ID: %s ",str);
 
-       printk("APIC at: 0x%X\n",mpc->mpc_lapic);
+       printk("MPTABLE: APIC at: 0x%X\n",mpc->mpc_lapic);
 
        /* save the local APIC address, it might be non-default */
        if (!acpi_lapic)
-       mp_lapic_addr = mpc->mpc_lapic;
+               mp_lapic_addr = mpc->mpc_lapic;
 
        /*
         *      Now process the configuration blocks.
@@ -302,7 +249,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
                                struct mpc_config_processor *m=
                                        (struct mpc_config_processor *)mpt;
                                if (!acpi_lapic)
-                               MP_processor_info(m);
+                                       MP_processor_info(m);
                                mpt += sizeof(*m);
                                count += sizeof(*m);
                                break;
@@ -321,8 +268,8 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
                                struct mpc_config_ioapic *m=
                                        (struct mpc_config_ioapic *)mpt;
                                MP_ioapic_info(m);
-                               mpt+=sizeof(*m);
-                               count+=sizeof(*m);
+                               mpt += sizeof(*m);
+                               count += sizeof(*m);
                                break;
                        }
                        case MP_INTSRC:
@@ -331,8 +278,8 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
                                        (struct mpc_config_intsrc *)mpt;
 
                                MP_intsrc_info(m);
-                               mpt+=sizeof(*m);
-                               count+=sizeof(*m);
+                               mpt += sizeof(*m);
+                               count += sizeof(*m);
                                break;
                        }
                        case MP_LINTSRC:
@@ -340,15 +287,15 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
                                struct mpc_config_lintsrc *m=
                                        (struct mpc_config_lintsrc *)mpt;
                                MP_lintsrc_info(m);
-                               mpt+=sizeof(*m);
-                               count+=sizeof(*m);
+                               mpt += sizeof(*m);
+                               count += sizeof(*m);
                                break;
                        }
                }
        }
        clustered_apic_check();
        if (!num_processors)
-               printk(KERN_ERR "SMP mptable: no processors registered!\n");
+               printk(KERN_ERR "MPTABLE: no processors registered!\n");
        return num_processors;
 }
 
@@ -444,13 +391,10 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
         * 2 CPUs, numbered 0 & 1.
         */
        processor.mpc_type = MP_PROCESSOR;
-       /* Either an integrated APIC or a discrete 82489DX. */
-       processor.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+       processor.mpc_apicver = 0;
        processor.mpc_cpuflag = CPU_ENABLED;
-       processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) |
-                                  (boot_cpu_data.x86_model << 4) |
-                                  boot_cpu_data.x86_mask;
-       processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+       processor.mpc_cpufeature = 0;
+       processor.mpc_featureflag = 0;
        processor.mpc_reserved[0] = 0;
        processor.mpc_reserved[1] = 0;
        for (i = 0; i < 2; i++) {
@@ -469,14 +413,6 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
                case 5:
                        memcpy(bus.mpc_bustype, "ISA   ", 6);
                        break;
-               case 2:
-               case 6:
-               case 3:
-                       memcpy(bus.mpc_bustype, "EISA  ", 6);
-                       break;
-               case 4:
-               case 7:
-                       memcpy(bus.mpc_bustype, "MCA   ", 6);
        }
        MP_bus_info(&bus);
        if (mpc_default_type > 4) {
@@ -487,7 +423,7 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
 
        ioapic.mpc_type = MP_IOAPIC;
        ioapic.mpc_apicid = 2;
-       ioapic.mpc_apicver = mpc_default_type > 4 ? 0x10 : 0x01;
+       ioapic.mpc_apicver = 0;
        ioapic.mpc_flags = MPC_APIC_USABLE;
        ioapic.mpc_apicaddr = 0xFEC00000;
        MP_ioapic_info(&ioapic);
@@ -530,13 +466,6 @@ void __init get_smp_config (void)
                printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
 
        printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
-       if (mpf->mpf_feature2 & (1<<7)) {
-               printk(KERN_INFO "    IMCR and PIC compatibility mode.\n");
-               pic_mode = 1;
-       } else {
-               printk(KERN_INFO "    Virtual Wire compatibility mode.\n");
-               pic_mode = 0;
-       }
 
        /*
         * Now see if we need to read further.
@@ -616,7 +545,7 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
        return 0;
 }
 
-void __init find_intel_smp (void)
+void __init find_smp_config(void)
 {
        unsigned int address;
 
@@ -633,9 +562,7 @@ void __init find_intel_smp (void)
                        smp_scan_config(0xF0000,0x10000))
                return;
        /*
-        * If it is an SMP machine we should know now, unless the
-        * configuration is in an EISA/MCA bus machine with an
-        * extended bios data area.
+        * If it is an SMP machine we should know now.
         *
         * there is a real-mode segmented pointer pointing to the
         * 4K EBDA area at 0x40E, calculate and scan it here.
@@ -656,69 +583,41 @@ void __init find_intel_smp (void)
         printk(KERN_INFO "No mptable found.\n");
 }
 
-/*
- * - Intel MP Configuration Table
- */
-void __init find_smp_config (void)
-{
-#ifdef CONFIG_X86_LOCAL_APIC
-       find_intel_smp();
-#endif
-}
-
-
 /* --------------------------------------------------------------------------
                             ACPI-based MP Configuration
    -------------------------------------------------------------------------- */
 
 #ifdef CONFIG_ACPI
 
-void __init mp_register_lapic_address (
-       u64                     address)
+void __init mp_register_lapic_address(u64 address)
 {
        mp_lapic_addr = (unsigned long) address;
-
        set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
-
        if (boot_cpu_id == -1U)
                boot_cpu_id = GET_APIC_ID(apic_read(APIC_ID));
-
-       Dprintk("Boot CPU = %d\n", boot_cpu_physical_apicid);
 }
 
-
-void __cpuinit mp_register_lapic (
-       u8                      id, 
-       u8                      enabled)
+void __cpuinit mp_register_lapic (u8 id, u8 enabled)
 {
        struct mpc_config_processor processor;
        int                     boot_cpu = 0;
        
-       if (id >= MAX_APICS) {
-               printk(KERN_WARNING "Processor #%d invalid (max %d)\n",
-                       id, MAX_APICS);
-               return;
-       }
-
-       if (id == boot_cpu_physical_apicid)
+       if (id == boot_cpu_id)
                boot_cpu = 1;
 
        processor.mpc_type = MP_PROCESSOR;
        processor.mpc_apicid = id;
-       processor.mpc_apicver = GET_APIC_VERSION(apic_read(APIC_LVR));
+       processor.mpc_apicver = 0;
        processor.mpc_cpuflag = (enabled ? CPU_ENABLED : 0);
        processor.mpc_cpuflag |= (boot_cpu ? CPU_BOOTPROCESSOR : 0);
-       processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | 
-               (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask;
-       processor.mpc_featureflag = boot_cpu_data.x86_capability[0];
+       processor.mpc_cpufeature = 0;
+       processor.mpc_featureflag = 0;
        processor.mpc_reserved[0] = 0;
        processor.mpc_reserved[1] = 0;
 
        MP_processor_info(&processor);
 }
 
-#ifdef CONFIG_X86_IO_APIC
-
 #define MP_ISA_BUS             0
 #define MP_MAX_IOAPIC_PIN      127
 
@@ -729,11 +628,9 @@ static struct mp_ioapic_routing {
        u32                     pin_programmed[4];
 } mp_ioapic_routing[MAX_IO_APICS];
 
-
-static int mp_find_ioapic (
-       int                     gsi)
+static int mp_find_ioapic(int gsi)
 {
-       int                     i = 0;
+       int i = 0;
 
        /* Find the IOAPIC that manages this GSI. */
        for (i = 0; i < nr_ioapics; i++) {
@@ -743,17 +640,12 @@ static int mp_find_ioapic (
        }
 
        printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
-
        return -1;
 }
-       
 
-void __init mp_register_ioapic (
-       u8                      id, 
-       u32                     address,
-       u32                     gsi_base)
+void __init mp_register_ioapic(u8 id, u32 address, u32 gsi_base)
 {
-       int                     idx = 0;
+       int idx = 0;
 
        if (nr_ioapics >= MAX_IO_APICS) {
                printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
@@ -774,7 +666,7 @@ void __init mp_register_ioapic (
 
        set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
        mp_ioapics[idx].mpc_apicid = id;
-       mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
+       mp_ioapics[idx].mpc_apicver = 0;
        
        /* 
         * Build basic IRQ lookup table to facilitate gsi->io_apic lookups
@@ -785,21 +677,15 @@ void __init mp_register_ioapic (
        mp_ioapic_routing[idx].gsi_end = gsi_base + 
                io_apic_get_redir_entries(idx);
 
-       printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
+       printk(KERN_INFO "IOAPIC[%d]: apic_id %d, address 0x%x, "
                "GSI %d-%d\n", idx, mp_ioapics[idx].mpc_apicid, 
-               mp_ioapics[idx].mpc_apicver, mp_ioapics[idx].mpc_apicaddr,
+               mp_ioapics[idx].mpc_apicaddr,
                mp_ioapic_routing[idx].gsi_start,
                mp_ioapic_routing[idx].gsi_end);
-
-       return;
 }
 
-
-void __init mp_override_legacy_irq (
-       u8                      bus_irq,
-       u8                      polarity, 
-       u8                      trigger, 
-       u32                     gsi)
+void __init
+mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32        gsi)
 {
        struct mpc_config_intsrc intsrc;
        int                     ioapic = -1;
@@ -837,22 +723,18 @@ void __init mp_override_legacy_irq (
        mp_irqs[mp_irq_entries] = intsrc;
        if (++mp_irq_entries == MAX_IRQ_SOURCES)
                panic("Max # of irq sources exceeded!\n");
-
-       return;
 }
 
-
-void __init mp_config_acpi_legacy_irqs (void)
+void __init mp_config_acpi_legacy_irqs(void)
 {
        struct mpc_config_intsrc intsrc;
-       int                     i = 0;
-       int                     ioapic = -1;
+       int i = 0;
+       int ioapic = -1;
 
        /* 
         * Fabricate the legacy ISA bus (bus #31).
         */
-       mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
-       Dprintk("Bus #%d is ISA\n", MP_ISA_BUS);
+       set_bit(MP_ISA_BUS, mp_bus_not_pci);
 
        /* 
         * Locate the IOAPIC that manages the ISA IRQs (0-15). 
@@ -905,24 +787,22 @@ void __init mp_config_acpi_legacy_irqs (void)
                if (++mp_irq_entries == MAX_IRQ_SOURCES)
                        panic("Max # of irq sources exceeded!\n");
        }
-
-       return;
 }
 
 #define MAX_GSI_NUM    4096
 
 int mp_register_gsi(u32 gsi, int triggering, int polarity)
 {
-       int                     ioapic = -1;
-       int                     ioapic_pin = 0;
-       int                     idx, bit = 0;
-       static int              pci_irq = 16;
+       int ioapic = -1;
+       int ioapic_pin = 0;
+       int idx, bit = 0;
+       static int pci_irq = 16;
        /*
         * Mapping between Global System Interrupts, which
         * represent all possible interrupts, to the IRQs
         * assigned to actual devices.
         */
-       static int              gsi_to_irq[MAX_GSI_NUM];
+       static int gsi_to_irq[MAX_GSI_NUM];
 
        if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
                return gsi;
@@ -996,6 +876,4 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
                polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
        return gsi;
 }
-
-#endif /*CONFIG_X86_IO_APIC*/
 #endif /*CONFIG_ACPI*/
index 5baa0c726e97c60aeea2badd1e552b8166f290d6..4d6fb047952e8abec336175d3bc5abe12dc76e76 100644 (file)
 #include <asm/mce.h>
 #include <asm/intel_arch_perfmon.h>
 
-/*
- * lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
- * - it may be reserved by some other driver, or not
- * - when not reserved by some other driver, it may be used for
- *   the NMI watchdog, or not
- *
- * This is maintained separately from nmi_active because the NMI
- * watchdog may also be driven from the I/O APIC timer.
+/* perfctr_nmi_owner tracks the ownership of the perfctr registers:
+ * evtsel_nmi_owner tracks the ownership of the event selection
+ * - different performance counters/ event selection may be reserved for
+ *   different subsystems this reservation system just tries to coordinate
+ *   things a little
  */
-static DEFINE_SPINLOCK(lapic_nmi_owner_lock);
-static unsigned int lapic_nmi_owner;
-#define LAPIC_NMI_WATCHDOG     (1<<0)
-#define LAPIC_NMI_RESERVED     (1<<1)
+static DEFINE_PER_CPU(unsigned, perfctr_nmi_owner);
+static DEFINE_PER_CPU(unsigned, evntsel_nmi_owner[2]);
+
+/* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's
+ * offset from MSR_P4_BSU_ESCR0.  It will be the max for all platforms (for now)
+ */
+#define NMI_MAX_COUNTER_BITS 66
 
 /* nmi_active:
- * +1: the lapic NMI watchdog is active, but can be disabled
- *  0: the lapic NMI watchdog has not been set up, and cannot
+ * >0: the lapic NMI watchdog is active, but can be disabled
+ * <0: the lapic NMI watchdog has not been set up, and cannot
  *     be enabled
- * -1: the lapic NMI watchdog is disabled, but can be enabled
+ *  0: the lapic NMI watchdog is disabled, but can be enabled
  */
-int nmi_active;                /* oprofile uses this */
+atomic_t nmi_active = ATOMIC_INIT(0);          /* oprofile uses this */
 int panic_on_timeout;
 
 unsigned int nmi_watchdog = NMI_DEFAULT;
 static unsigned int nmi_hz = HZ;
-static unsigned int nmi_perfctr_msr;   /* the MSR to reset in NMI handler */
-static unsigned int nmi_p4_cccr_val;
 
-/* Note that these events don't tick when the CPU idles. This means
-   the frequency varies with CPU load. */
+struct nmi_watchdog_ctlblk {
+       int enabled;
+       u64 check_bit;
+       unsigned int cccr_msr;
+       unsigned int perfctr_msr;  /* the MSR to reset in NMI handler */
+       unsigned int evntsel_msr;  /* the MSR to select the events to handle */
+};
+static DEFINE_PER_CPU(struct nmi_watchdog_ctlblk, nmi_watchdog_ctlblk);
 
-#define K7_EVNTSEL_ENABLE      (1 << 22)
-#define K7_EVNTSEL_INT         (1 << 20)
-#define K7_EVNTSEL_OS          (1 << 17)
-#define K7_EVNTSEL_USR         (1 << 16)
-#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING   0x76
-#define K7_NMI_EVENT           K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
+/* local prototypes */
+static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu);
 
-#define ARCH_PERFMON_NMI_EVENT_SEL     ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
-#define ARCH_PERFMON_NMI_EVENT_UMASK   ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+/* converts an msr to an appropriate reservation bit */
+static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
+{
+       /* returns the bit offset of the performance counter register */
+       switch (boot_cpu_data.x86_vendor) {
+       case X86_VENDOR_AMD:
+               return (msr - MSR_K7_PERFCTR0);
+       case X86_VENDOR_INTEL:
+               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+                       return (msr - MSR_ARCH_PERFMON_PERFCTR0);
+               else
+                       return (msr - MSR_P4_BPU_PERFCTR0);
+       }
+       return 0;
+}
 
-#define MSR_P4_MISC_ENABLE     0x1A0
-#define MSR_P4_MISC_ENABLE_PERF_AVAIL  (1<<7)
-#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL        (1<<12)
-#define MSR_P4_PERFCTR0                0x300
-#define MSR_P4_CCCR0           0x360
-#define P4_ESCR_EVENT_SELECT(N)        ((N)<<25)
-#define P4_ESCR_OS             (1<<3)
-#define P4_ESCR_USR            (1<<2)
-#define P4_CCCR_OVF_PMI0       (1<<26)
-#define P4_CCCR_OVF_PMI1       (1<<27)
-#define P4_CCCR_THRESHOLD(N)   ((N)<<20)
-#define P4_CCCR_COMPLEMENT     (1<<19)
-#define P4_CCCR_COMPARE                (1<<18)
-#define P4_CCCR_REQUIRED       (3<<16)
-#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
-#define P4_CCCR_ENABLE         (1<<12)
-/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
-   CRU_ESCR0 (with any non-null event selector) through a complemented
-   max threshold. [IA32-Vol3, Section 14.9.9] */
-#define MSR_P4_IQ_COUNTER0     0x30C
-#define P4_NMI_CRU_ESCR0       (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
-#define P4_NMI_IQ_CCCR0        \
-       (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT|     \
-        P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
+/* converts an msr to an appropriate reservation bit */
+static inline unsigned int nmi_evntsel_msr_to_bit(unsigned int msr)
+{
+       /* returns the bit offset of the event selection register */
+       switch (boot_cpu_data.x86_vendor) {
+       case X86_VENDOR_AMD:
+               return (msr - MSR_K7_EVNTSEL0);
+       case X86_VENDOR_INTEL:
+               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
+                       return (msr - MSR_ARCH_PERFMON_EVENTSEL0);
+               else
+                       return (msr - MSR_P4_BSU_ESCR0);
+       }
+       return 0;
+}
+
+/* checks for a bit availability (hack for oprofile) */
+int avail_to_resrv_perfctr_nmi_bit(unsigned int counter)
+{
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner)));
+}
+
+/* checks the an msr for availability */
+int avail_to_resrv_perfctr_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_perfctr_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       return (!test_bit(counter, &__get_cpu_var(perfctr_nmi_owner)));
+}
+
+int reserve_perfctr_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_perfctr_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       if (!test_and_set_bit(counter, &__get_cpu_var(perfctr_nmi_owner)))
+               return 1;
+       return 0;
+}
+
+void release_perfctr_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_perfctr_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       clear_bit(counter, &__get_cpu_var(perfctr_nmi_owner));
+}
+
+int reserve_evntsel_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_evntsel_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       if (!test_and_set_bit(counter, &__get_cpu_var(evntsel_nmi_owner)))
+               return 1;
+       return 0;
+}
+
+void release_evntsel_nmi(unsigned int msr)
+{
+       unsigned int counter;
+
+       counter = nmi_evntsel_msr_to_bit(msr);
+       BUG_ON(counter > NMI_MAX_COUNTER_BITS);
+
+       clear_bit(counter, &__get_cpu_var(evntsel_nmi_owner));
+}
 
 static __cpuinit inline int nmi_known_cpu(void)
 {
@@ -109,7 +176,7 @@ static __cpuinit inline int nmi_known_cpu(void)
 }
 
 /* Run after command line and cpu_init init, but before all other checks */
-void __cpuinit nmi_watchdog_default(void)
+void nmi_watchdog_default(void)
 {
        if (nmi_watchdog != NMI_DEFAULT)
                return;
@@ -145,6 +212,12 @@ int __init check_nmi_watchdog (void)
        int *counts;
        int cpu;
 
+       if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT))
+               return 0;
+
+       if (!atomic_read(&nmi_active))
+               return 0;
+
        counts = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
        if (!counts)
                return -1;
@@ -162,26 +235,43 @@ int __init check_nmi_watchdog (void)
        mdelay((10*1000)/nmi_hz); // wait 10 ticks
 
        for_each_online_cpu(cpu) {
+               if (!per_cpu(nmi_watchdog_ctlblk, cpu).enabled)
+                       continue;
                if (cpu_pda(cpu)->__nmi_count - counts[cpu] <= 5) {
-                       endflag = 1;
                        printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
                               cpu,
                               counts[cpu],
                               cpu_pda(cpu)->__nmi_count);
-                       nmi_active = 0;
-                       lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
-                       nmi_perfctr_msr = 0;
-                       kfree(counts);
-                       return -1;
+                       per_cpu(nmi_watchdog_ctlblk, cpu).enabled = 0;
+                       atomic_dec(&nmi_active);
                }
        }
+       if (!atomic_read(&nmi_active)) {
+               kfree(counts);
+               atomic_set(&nmi_active, -1);
+               return -1;
+       }
        endflag = 1;
        printk("OK.\n");
 
        /* now that we know it works we can reduce NMI frequency to
           something more reasonable; makes a difference in some configs */
-       if (nmi_watchdog == NMI_LOCAL_APIC)
+       if (nmi_watchdog == NMI_LOCAL_APIC) {
+               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;
+               }
+       }
 
        kfree(counts);
        return 0;
@@ -201,91 +291,65 @@ int __init setup_nmi_watchdog(char *str)
 
        get_option(&str, &nmi);
 
-       if (nmi >= NMI_INVALID)
+       if ((nmi >= NMI_INVALID) || (nmi < NMI_NONE))
                return 0;
+
+       if ((nmi == NMI_LOCAL_APIC) && (nmi_known_cpu() == 0))
+               return 0;  /* no lapic support */
        nmi_watchdog = nmi;
        return 1;
 }
 
 __setup("nmi_watchdog=", setup_nmi_watchdog);
 
-static void disable_intel_arch_watchdog(void);
-
 static void disable_lapic_nmi_watchdog(void)
 {
-       if (nmi_active <= 0)
+       BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
+
+       if (atomic_read(&nmi_active) <= 0)
                return;
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_AMD:
-               wrmsr(MSR_K7_EVNTSEL0, 0, 0);
-               break;
-       case X86_VENDOR_INTEL:
-               if (boot_cpu_data.x86 == 15) {
-                       wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
-                       wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
-               } else if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
-                       disable_intel_arch_watchdog();
-               }
-               break;
-       }
-       nmi_active = -1;
-       /* tell do_nmi() and others that we're not active any more */
-       nmi_watchdog = 0;
-}
 
-static void enable_lapic_nmi_watchdog(void)
-{
-       if (nmi_active < 0) {
-               nmi_watchdog = NMI_LOCAL_APIC;
-               touch_nmi_watchdog();
-               setup_apic_nmi_watchdog();
-       }
+       on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
+
+       BUG_ON(atomic_read(&nmi_active) != 0);
 }
 
-int reserve_lapic_nmi(void)
+static void enable_lapic_nmi_watchdog(void)
 {
-       unsigned int old_owner;
+       BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
 
-       spin_lock(&lapic_nmi_owner_lock);
-       old_owner = lapic_nmi_owner;
-       lapic_nmi_owner |= LAPIC_NMI_RESERVED;
-       spin_unlock(&lapic_nmi_owner_lock);
-       if (old_owner & LAPIC_NMI_RESERVED)
-               return -EBUSY;
-       if (old_owner & LAPIC_NMI_WATCHDOG)
-               disable_lapic_nmi_watchdog();
-       return 0;
-}
+       /* are we already enabled */
+       if (atomic_read(&nmi_active) != 0)
+               return;
 
-void release_lapic_nmi(void)
-{
-       unsigned int new_owner;
+       /* are we lapic aware */
+       if (nmi_known_cpu() <= 0)
+               return;
 
-       spin_lock(&lapic_nmi_owner_lock);
-       new_owner = lapic_nmi_owner & ~LAPIC_NMI_RESERVED;
-       lapic_nmi_owner = new_owner;
-       spin_unlock(&lapic_nmi_owner_lock);
-       if (new_owner & LAPIC_NMI_WATCHDOG)
-               enable_lapic_nmi_watchdog();
+       on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
+       touch_nmi_watchdog();
 }
 
 void disable_timer_nmi_watchdog(void)
 {
-       if ((nmi_watchdog != NMI_IO_APIC) || (nmi_active <= 0))
+       BUG_ON(nmi_watchdog != NMI_IO_APIC);
+
+       if (atomic_read(&nmi_active) <= 0)
                return;
 
        disable_irq(0);
-       unset_nmi_callback();
-       nmi_active = -1;
-       nmi_watchdog = NMI_NONE;
+       on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
+
+       BUG_ON(atomic_read(&nmi_active) != 0);
 }
 
 void enable_timer_nmi_watchdog(void)
 {
-       if (nmi_active < 0) {
-               nmi_watchdog = NMI_IO_APIC;
+       BUG_ON(nmi_watchdog != NMI_IO_APIC);
+
+       if (atomic_read(&nmi_active) == 0) {
                touch_nmi_watchdog();
-               nmi_active = 1;
+               on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
                enable_irq(0);
        }
 }
@@ -296,15 +360,20 @@ static int nmi_pm_active; /* nmi_active before suspend */
 
 static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
 {
-       nmi_pm_active = nmi_active;
-       disable_lapic_nmi_watchdog();
+       /* only CPU0 goes here, other CPUs should be offline */
+       nmi_pm_active = atomic_read(&nmi_active);
+       stop_apic_nmi_watchdog(NULL);
+       BUG_ON(atomic_read(&nmi_active) != 0);
        return 0;
 }
 
 static int lapic_nmi_resume(struct sys_device *dev)
 {
-       if (nmi_pm_active > 0)
-       enable_lapic_nmi_watchdog();
+       /* only CPU0 goes here, other CPUs should be offline */
+       if (nmi_pm_active > 0) {
+               setup_apic_nmi_watchdog(NULL);
+               touch_nmi_watchdog();
+       }
        return 0;
 }
 
@@ -323,7 +392,13 @@ static int __init init_lapic_nmi_sysfs(void)
 {
        int error;
 
-       if (nmi_active == 0 || nmi_watchdog != NMI_LOCAL_APIC)
+       /* should really be a BUG_ON but b/c this is an
+        * init call, it just doesn't work.  -dcz
+        */
+       if (nmi_watchdog != NMI_LOCAL_APIC)
+               return 0;
+
+       if ( atomic_read(&nmi_active) < 0 )
                return 0;
 
        error = sysdev_class_register(&nmi_sysclass);
@@ -341,74 +416,209 @@ late_initcall(init_lapic_nmi_sysfs);
  * Original code written by Keith Owens.
  */
 
-static void clear_msr_range(unsigned int base, unsigned int n)
-{
-       unsigned int i;
+/* Note that these events don't tick when the CPU idles. This means
+   the frequency varies with CPU load. */
 
-       for(i = 0; i < n; ++i)
-               wrmsr(base+i, 0, 0);
-}
+#define K7_EVNTSEL_ENABLE      (1 << 22)
+#define K7_EVNTSEL_INT         (1 << 20)
+#define K7_EVNTSEL_OS          (1 << 17)
+#define K7_EVNTSEL_USR         (1 << 16)
+#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING   0x76
+#define K7_NMI_EVENT           K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
 
-static void setup_k7_watchdog(void)
+static int setup_k7_watchdog(void)
 {
-       int i;
+       unsigned int perfctr_msr, evntsel_msr;
        unsigned int evntsel;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
-       nmi_perfctr_msr = MSR_K7_PERFCTR0;
+       perfctr_msr = MSR_K7_PERFCTR0;
+       evntsel_msr = MSR_K7_EVNTSEL0;
+       if (!reserve_perfctr_nmi(perfctr_msr))
+               goto fail;
 
-       for(i = 0; i < 4; ++i) {
-               /* Simulator may not support it */
-               if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL)) {
-                       nmi_perfctr_msr = 0;
-                       return;
-               }
-               wrmsrl(MSR_K7_PERFCTR0+i, 0UL);
-       }
+       if (!reserve_evntsel_nmi(evntsel_msr))
+               goto fail1;
+
+       /* Simulator may not support it */
+       if (checking_wrmsrl(evntsel_msr, 0UL))
+               goto fail2;
+       wrmsrl(perfctr_msr, 0UL);
 
        evntsel = K7_EVNTSEL_INT
                | K7_EVNTSEL_OS
                | K7_EVNTSEL_USR
                | K7_NMI_EVENT;
 
-       wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
-       wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz * 1000 / nmi_hz));
+       /* setup the timer */
+       wrmsr(evntsel_msr, evntsel, 0);
+       wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
        apic_write(APIC_LVTPC, APIC_DM_NMI);
        evntsel |= K7_EVNTSEL_ENABLE;
-       wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
+       wrmsr(evntsel_msr, evntsel, 0);
+
+       wd->perfctr_msr = perfctr_msr;
+       wd->evntsel_msr = evntsel_msr;
+       wd->cccr_msr = 0;  //unused
+       wd->check_bit = 1ULL<<63;
+       return 1;
+fail2:
+       release_evntsel_nmi(evntsel_msr);
+fail1:
+       release_perfctr_nmi(perfctr_msr);
+fail:
+       return 0;
 }
 
-static void disable_intel_arch_watchdog(void)
+static void stop_k7_watchdog(void)
 {
-       unsigned ebx;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
-       /*
-        * Check whether the Architectural PerfMon supports
-        * Unhalted Core Cycles Event or not.
-        * NOTE: Corresponding bit = 0 in ebp indicates event present.
+       wrmsr(wd->evntsel_msr, 0, 0);
+
+       release_evntsel_nmi(wd->evntsel_msr);
+       release_perfctr_nmi(wd->perfctr_msr);
+}
+
+/* Note that these events don't tick when the CPU idles. This means
+   the frequency varies with CPU load. */
+
+#define MSR_P4_MISC_ENABLE_PERF_AVAIL  (1<<7)
+#define P4_ESCR_EVENT_SELECT(N)        ((N)<<25)
+#define P4_ESCR_OS             (1<<3)
+#define P4_ESCR_USR            (1<<2)
+#define P4_CCCR_OVF_PMI0       (1<<26)
+#define P4_CCCR_OVF_PMI1       (1<<27)
+#define P4_CCCR_THRESHOLD(N)   ((N)<<20)
+#define P4_CCCR_COMPLEMENT     (1<<19)
+#define P4_CCCR_COMPARE                (1<<18)
+#define P4_CCCR_REQUIRED       (3<<16)
+#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
+#define P4_CCCR_ENABLE         (1<<12)
+#define P4_CCCR_OVF            (1<<31)
+/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
+   CRU_ESCR0 (with any non-null event selector) through a complemented
+   max threshold. [IA32-Vol3, Section 14.9.9] */
+
+static int setup_p4_watchdog(void)
+{
+       unsigned int perfctr_msr, evntsel_msr, cccr_msr;
+       unsigned int evntsel, cccr_val;
+       unsigned int misc_enable, dummy;
+       unsigned int ht_num;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       rdmsr(MSR_IA32_MISC_ENABLE, misc_enable, dummy);
+       if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
+               return 0;
+
+#ifdef CONFIG_SMP
+       /* detect which hyperthread we are on */
+       if (smp_num_siblings == 2) {
+               unsigned int ebx, apicid;
+
+               ebx = cpuid_ebx(1);
+               apicid = (ebx >> 24) & 0xff;
+               ht_num = apicid & 1;
+       } else
+#endif
+               ht_num = 0;
+
+       /* performance counters are shared resources
+        * assign each hyperthread its own set
+        * (re-use the ESCR0 register, seems safe
+        * and keeps the cccr_val the same)
         */
-       ebx = cpuid_ebx(10);
-       if (!(ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
-               wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, 0, 0);
+       if (!ht_num) {
+               /* logical cpu 0 */
+               perfctr_msr = MSR_P4_IQ_PERFCTR0;
+               evntsel_msr = MSR_P4_CRU_ESCR0;
+               cccr_msr = MSR_P4_IQ_CCCR0;
+               cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4);
+       } else {
+               /* logical cpu 1 */
+               perfctr_msr = MSR_P4_IQ_PERFCTR1;
+               evntsel_msr = MSR_P4_CRU_ESCR0;
+               cccr_msr = MSR_P4_IQ_CCCR1;
+               cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4);
+       }
+
+       if (!reserve_perfctr_nmi(perfctr_msr))
+               goto fail;
+
+       if (!reserve_evntsel_nmi(evntsel_msr))
+               goto fail1;
+
+       evntsel = P4_ESCR_EVENT_SELECT(0x3F)
+               | P4_ESCR_OS
+               | P4_ESCR_USR;
+
+       cccr_val |= P4_CCCR_THRESHOLD(15)
+                | P4_CCCR_COMPLEMENT
+                | P4_CCCR_COMPARE
+                | P4_CCCR_REQUIRED;
+
+       wrmsr(evntsel_msr, evntsel, 0);
+       wrmsr(cccr_msr, cccr_val, 0);
+       wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+       cccr_val |= P4_CCCR_ENABLE;
+       wrmsr(cccr_msr, cccr_val, 0);
+
+       wd->perfctr_msr = perfctr_msr;
+       wd->evntsel_msr = evntsel_msr;
+       wd->cccr_msr = cccr_msr;
+       wd->check_bit = 1ULL<<39;
+       return 1;
+fail1:
+       release_perfctr_nmi(perfctr_msr);
+fail:
+       return 0;
+}
+
+static void stop_p4_watchdog(void)
+{
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       wrmsr(wd->cccr_msr, 0, 0);
+       wrmsr(wd->evntsel_msr, 0, 0);
+
+       release_evntsel_nmi(wd->evntsel_msr);
+       release_perfctr_nmi(wd->perfctr_msr);
 }
 
+#define ARCH_PERFMON_NMI_EVENT_SEL     ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL
+#define ARCH_PERFMON_NMI_EVENT_UMASK   ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK
+
 static int setup_intel_arch_watchdog(void)
 {
+       unsigned int ebx;
+       union cpuid10_eax eax;
+       unsigned int unused;
+       unsigned int perfctr_msr, evntsel_msr;
        unsigned int evntsel;
-       unsigned ebx;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
        /*
         * Check whether the Architectural PerfMon supports
         * Unhalted Core Cycles Event or not.
-        * NOTE: Corresponding bit = 0 in ebp indicates event present.
+        * NOTE: Corresponding bit = 0 in ebx indicates event present.
         */
-       ebx = cpuid_ebx(10);
-       if ((ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
-               return 0;
+       cpuid(10, &(eax.full), &ebx, &unused, &unused);
+       if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
+           (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+               goto fail;
+
+       perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
+       evntsel_msr = MSR_ARCH_PERFMON_EVENTSEL0;
 
-       nmi_perfctr_msr = MSR_ARCH_PERFMON_PERFCTR0;
+       if (!reserve_perfctr_nmi(perfctr_msr))
+               goto fail;
 
-       clear_msr_range(MSR_ARCH_PERFMON_EVENTSEL0, 2);
-       clear_msr_range(MSR_ARCH_PERFMON_PERFCTR0, 2);
+       if (!reserve_evntsel_nmi(evntsel_msr))
+               goto fail1;
+
+       wrmsrl(perfctr_msr, 0UL);
 
        evntsel = ARCH_PERFMON_EVENTSEL_INT
                | ARCH_PERFMON_EVENTSEL_OS
@@ -416,84 +626,122 @@ static int setup_intel_arch_watchdog(void)
                | ARCH_PERFMON_NMI_EVENT_SEL
                | ARCH_PERFMON_NMI_EVENT_UMASK;
 
-       wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
-       wrmsrl(MSR_ARCH_PERFMON_PERFCTR0, -((u64)cpu_khz * 1000 / nmi_hz));
+       /* setup the timer */
+       wrmsr(evntsel_msr, evntsel, 0);
+       wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
+
        apic_write(APIC_LVTPC, APIC_DM_NMI);
        evntsel |= ARCH_PERFMON_EVENTSEL0_ENABLE;
-       wrmsr(MSR_ARCH_PERFMON_EVENTSEL0, evntsel, 0);
+       wrmsr(evntsel_msr, evntsel, 0);
+
+       wd->perfctr_msr = perfctr_msr;
+       wd->evntsel_msr = evntsel_msr;
+       wd->cccr_msr = 0;  //unused
+       wd->check_bit = 1ULL << (eax.split.bit_width - 1);
        return 1;
+fail1:
+       release_perfctr_nmi(perfctr_msr);
+fail:
+       return 0;
 }
 
-
-static int setup_p4_watchdog(void)
+static void stop_intel_arch_watchdog(void)
 {
-       unsigned int misc_enable, dummy;
+       unsigned int ebx;
+       union cpuid10_eax eax;
+       unsigned int unused;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
-       rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
-       if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
-               return 0;
+       /*
+        * Check whether the Architectural PerfMon supports
+        * Unhalted Core Cycles Event or not.
+        * NOTE: Corresponding bit = 0 in ebx indicates event present.
+        */
+       cpuid(10, &(eax.full), &ebx, &unused, &unused);
+       if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX+1)) ||
+           (ebx & ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT))
+               return;
 
-       nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
-       nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
-#ifdef CONFIG_SMP
-       if (smp_num_siblings == 2)
-               nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;
-#endif
+       wrmsr(wd->evntsel_msr, 0, 0);
 
-       if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
-               clear_msr_range(0x3F1, 2);
-       /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
-          docs doesn't fully define it, so leave it alone for now. */
-       if (boot_cpu_data.x86_model >= 0x3) {
-               /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
-               clear_msr_range(0x3A0, 26);
-               clear_msr_range(0x3BC, 3);
-       } else {
-               clear_msr_range(0x3A0, 31);
-       }
-       clear_msr_range(0x3C0, 6);
-       clear_msr_range(0x3C8, 6);
-       clear_msr_range(0x3E0, 2);
-       clear_msr_range(MSR_P4_CCCR0, 18);
-       clear_msr_range(MSR_P4_PERFCTR0, 18);
-
-       wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
-       wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
-       Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz * 1000UL / nmi_hz));
-       wrmsrl(MSR_P4_IQ_COUNTER0, -((u64)cpu_khz * 1000 / nmi_hz));
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-       wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
-       return 1;
+       release_evntsel_nmi(wd->evntsel_msr);
+       release_perfctr_nmi(wd->perfctr_msr);
 }
 
-void setup_apic_nmi_watchdog(void)
+void setup_apic_nmi_watchdog(void *unused)
 {
-       switch (boot_cpu_data.x86_vendor) {
-       case X86_VENDOR_AMD:
-               if (boot_cpu_data.x86 != 15)
-                       return;
-               if (strstr(boot_cpu_data.x86_model_id, "Screwdriver"))
-                       return;
-               setup_k7_watchdog();
-               break;
-       case X86_VENDOR_INTEL:
-               if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
-                       if (!setup_intel_arch_watchdog())
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+
+       /* only support LOCAL and IO APICs for now */
+       if ((nmi_watchdog != NMI_LOCAL_APIC) &&
+           (nmi_watchdog != NMI_IO_APIC))
+               return;
+
+       if (wd->enabled == 1)
+               return;
+
+       /* cheap hack to support suspend/resume */
+       /* if cpu0 is not active neither should the other cpus */
+       if ((smp_processor_id() != 0) && (atomic_read(&nmi_active) <= 0))
+               return;
+
+       if (nmi_watchdog == NMI_LOCAL_APIC) {
+               switch (boot_cpu_data.x86_vendor) {
+               case X86_VENDOR_AMD:
+                       if (strstr(boot_cpu_data.x86_model_id, "Screwdriver"))
                                return;
-               } else if (boot_cpu_data.x86 == 15) {
+                       if (!setup_k7_watchdog())
+                               return;
+                       break;
+               case X86_VENDOR_INTEL:
+                       if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+                               if (!setup_intel_arch_watchdog())
+                                       return;
+                               break;
+                       }
                        if (!setup_p4_watchdog())
                                return;
-               } else {
+                       break;
+               default:
                        return;
                }
+       }
+       wd->enabled = 1;
+       atomic_inc(&nmi_active);
+}
+
+void stop_apic_nmi_watchdog(void *unused)
+{
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
 
-               break;
+       /* only support LOCAL and IO APICs for now */
+       if ((nmi_watchdog != NMI_LOCAL_APIC) &&
+           (nmi_watchdog != NMI_IO_APIC))
+               return;
 
-       default:
+       if (wd->enabled == 0)
                return;
+
+       if (nmi_watchdog == NMI_LOCAL_APIC) {
+               switch (boot_cpu_data.x86_vendor) {
+               case X86_VENDOR_AMD:
+                       if (strstr(boot_cpu_data.x86_model_id, "Screwdriver"))
+                               return;
+                       stop_k7_watchdog();
+                       break;
+               case X86_VENDOR_INTEL:
+                       if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
+                               stop_intel_arch_watchdog();
+                               break;
+                       }
+                       stop_p4_watchdog();
+                       break;
+               default:
+                       return;
+               }
        }
-       lapic_nmi_owner = LAPIC_NMI_WATCHDOG;
-       nmi_active = 1;
+       wd->enabled = 0;
+       atomic_dec(&nmi_active);
 }
 
 /*
@@ -526,93 +774,109 @@ void touch_nmi_watchdog (void)
        touch_softlockup_watchdog();
 }
 
-void __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
+int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
 {
        int sum;
        int touched = 0;
+       struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
+       u64 dummy;
+       int rc=0;
+
+       /* check for other users first */
+       if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
+                       == NOTIFY_STOP) {
+               rc = 1;
+               touched = 1;
+       }
 
        sum = read_pda(apic_timer_irqs);
        if (__get_cpu_var(nmi_touch)) {
                __get_cpu_var(nmi_touch) = 0;
                touched = 1;
        }
+
 #ifdef CONFIG_X86_MCE
        /* Could check oops_in_progress here too, but it's safer
           not too */
        if (atomic_read(&mce_entry) > 0)
                touched = 1;
 #endif
+       /* if the apic timer isn't firing, this cpu isn't doing much */
        if (!touched && __get_cpu_var(last_irq_sum) == sum) {
                /*
                 * Ayiee, looks like this CPU is stuck ...
                 * wait a few IRQs (5 seconds) before doing the oops ...
                 */
                local_inc(&__get_cpu_var(alert_counter));
-               if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz) {
-                       if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
-                                                       == NOTIFY_STOP) {
-                               local_set(&__get_cpu_var(alert_counter), 0);
-                               return;
-                       }
-                       die_nmi("NMI Watchdog detected LOCKUP on CPU %d\n", regs);
-               }
+               if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz)
+                       die_nmi("NMI Watchdog detected LOCKUP on CPU %d\n", regs,
+                               panic_on_timeout);
        } else {
                __get_cpu_var(last_irq_sum) = sum;
                local_set(&__get_cpu_var(alert_counter), 0);
        }
-       if (nmi_perfctr_msr) {
-               if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
-                       /*
-                        * P4 quirks:
-                        * - An overflown perfctr will assert its interrupt
-                        *   until the OVF flag in its CCCR is cleared.
-                        * - LVTPC is masked on interrupt and must be
-                        *   unmasked by the LVTPC handler.
-                        */
-                       wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
-                       apic_write(APIC_LVTPC, APIC_DM_NMI);
-               } else if (nmi_perfctr_msr == MSR_ARCH_PERFMON_PERFCTR0) {
-                       /*
-                        * For Intel based architectural perfmon
-                        * - LVTPC is masked on interrupt and must be
-                        *   unmasked by the LVTPC handler.
+
+       /* see if the nmi watchdog went off */
+       if (wd->enabled) {
+               if (nmi_watchdog == NMI_LOCAL_APIC) {
+                       rdmsrl(wd->perfctr_msr, dummy);
+                       if (dummy & wd->check_bit){
+                               /* this wasn't a watchdog timer interrupt */
+                               goto done;
+                       }
+
+                       /* only Intel uses the cccr msr */
+                       if (wd->cccr_msr != 0) {
+                               /*
+                                * P4 quirks:
+                                * - An overflown perfctr will assert its interrupt
+                                *   until the OVF flag in its CCCR is cleared.
+                                * - LVTPC is masked on interrupt and must be
+                                *   unmasked by the LVTPC handler.
+                                */
+                               rdmsrl(wd->cccr_msr, dummy);
+                               dummy &= ~P4_CCCR_OVF;
+                               wrmsrl(wd->cccr_msr, dummy);
+                               apic_write(APIC_LVTPC, APIC_DM_NMI);
+                       } 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);
+                       }
+                       /* 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.
+                        * just assume it was a watchdog timer interrupt
+                        * This matches the old behaviour.
                         */
-                       apic_write(APIC_LVTPC, APIC_DM_NMI);
-               }
-               wrmsrl(nmi_perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
+                       rc = 1;
+               } else
+                       printk(KERN_WARNING "Unknown enabled NMI hardware?!\n");
        }
+done:
+       return rc;
 }
 
-static __kprobes int dummy_nmi_callback(struct pt_regs * regs, int cpu)
-{
-       return 0;
-}
-static nmi_callback_t nmi_callback = dummy_nmi_callback;
 asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code)
 {
-       int cpu = safe_smp_processor_id();
-
        nmi_enter();
        add_pda(__nmi_count,1);
-       if (!rcu_dereference(nmi_callback)(regs, cpu))
-               default_do_nmi(regs);
+       default_do_nmi(regs);
        nmi_exit();
 }
 
-void set_nmi_callback(nmi_callback_t callback)
+int do_nmi_callback(struct pt_regs * regs, int cpu)
 {
-       vmalloc_sync_all();
-       rcu_assign_pointer(nmi_callback, callback);
-}
-EXPORT_SYMBOL_GPL(set_nmi_callback);
-
-void unset_nmi_callback(void)
-{
-       nmi_callback = dummy_nmi_callback;
+#ifdef CONFIG_SYSCTL
+       if (unknown_nmi_panic)
+               return unknown_nmi_panic_callback(regs, cpu);
+#endif
+       return 0;
 }
-EXPORT_SYMBOL_GPL(unset_nmi_callback);
 
 #ifdef CONFIG_SYSCTL
 
@@ -621,36 +885,42 @@ static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu)
        unsigned char reason = get_nmi_reason();
        char buf[64];
 
-       if (!(reason & 0xc0)) {
-               sprintf(buf, "NMI received for unknown reason %02x\n", reason);
-               die_nmi(buf,regs);
-       }
+       sprintf(buf, "NMI received for unknown reason %02x\n", reason);
+       die_nmi(buf, regs, 1);  /* Always panic here */
        return 0;
 }
 
 /*
- * proc handler for /proc/sys/kernel/unknown_nmi_panic
+ * proc handler for /proc/sys/kernel/nmi
  */
-int proc_unknown_nmi_panic(struct ctl_table *table, int write, struct file *file,
+int proc_nmi_enabled(struct ctl_table *table, int write, struct file *file,
                        void __user *buffer, size_t *length, loff_t *ppos)
 {
        int old_state;
 
-       old_state = unknown_nmi_panic;
+       nmi_watchdog_enabled = (atomic_read(&nmi_active) > 0) ? 1 : 0;
+       old_state = nmi_watchdog_enabled;
        proc_dointvec(table, write, file, buffer, length, ppos);
-       if (!!old_state == !!unknown_nmi_panic)
+       if (!!old_state == !!nmi_watchdog_enabled)
                return 0;
 
-       if (unknown_nmi_panic) {
-               if (reserve_lapic_nmi() < 0) {
-                       unknown_nmi_panic = 0;
-                       return -EBUSY;
-               } else {
-                       set_nmi_callback(unknown_nmi_panic_callback);
-               }
+       if (atomic_read(&nmi_active) < 0) {
+               printk( KERN_WARNING "NMI watchdog is permanently disabled\n");
+               return -EIO;
+       }
+
+       /* if nmi_watchdog is not set yet, then set it */
+       nmi_watchdog_default();
+
+       if (nmi_watchdog == NMI_LOCAL_APIC) {
+               if (nmi_watchdog_enabled)
+                       enable_lapic_nmi_watchdog();
+               else
+                       disable_lapic_nmi_watchdog();
        } else {
-               release_lapic_nmi();
-               unset_nmi_callback();
+               printk( KERN_WARNING
+                       "NMI watchdog doesn't know what hardware to touch\n");
+               return -EIO;
        }
        return 0;
 }
@@ -659,8 +929,12 @@ int proc_unknown_nmi_panic(struct ctl_table *table, int write, struct file *file
 
 EXPORT_SYMBOL(nmi_active);
 EXPORT_SYMBOL(nmi_watchdog);
-EXPORT_SYMBOL(reserve_lapic_nmi);
-EXPORT_SYMBOL(release_lapic_nmi);
+EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi);
+EXPORT_SYMBOL(avail_to_resrv_perfctr_nmi_bit);
+EXPORT_SYMBOL(reserve_perfctr_nmi);
+EXPORT_SYMBOL(release_perfctr_nmi);
+EXPORT_SYMBOL(reserve_evntsel_nmi);
+EXPORT_SYMBOL(release_evntsel_nmi);
 EXPORT_SYMBOL(disable_timer_nmi_watchdog);
 EXPORT_SYMBOL(enable_timer_nmi_watchdog);
 EXPORT_SYMBOL(touch_nmi_watchdog);
index 146924ba5df5b5d86ec3aea9b2a1edddc17f83e8..cfb09b07ae99864b90062b6f96fc60201341a654 100644 (file)
@@ -86,7 +86,8 @@
 
 #define MAX_NUM_OF_PHBS                8 /* how many PHBs in total? */
 #define MAX_NUM_CHASSIS                8 /* max number of chassis */
-#define MAX_PHB_BUS_NUM                (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2) /* max dev->bus->number */
+/* MAX_PHB_BUS_NUM is the maximal possible dev->bus->number */
+#define MAX_PHB_BUS_NUM                (MAX_NUM_OF_PHBS * MAX_NUM_CHASSIS * 2)
 #define PHBS_PER_CALGARY       4
 
 /* register offsets in Calgary's internal register space */
@@ -111,31 +112,49 @@ static const unsigned long phb_offsets[] = {
        0xB000 /* PHB3 */
 };
 
-static char bus_to_phb[MAX_PHB_BUS_NUM];
-void* tce_table_kva[MAX_PHB_BUS_NUM];
 unsigned int specified_table_size = TCE_TABLE_SIZE_UNSPECIFIED;
 static int translate_empty_slots __read_mostly = 0;
 static int calgary_detected __read_mostly = 0;
 
-/*
- * the bitmap of PHBs the user requested that we disable
- * translation on.
- */
-static DECLARE_BITMAP(translation_disabled, MAX_PHB_BUS_NUM);
+struct calgary_bus_info {
+       void *tce_space;
+       unsigned char translation_disabled;
+       signed char phbid;
+};
+
+static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, };
 
 static void tce_cache_blast(struct iommu_table *tbl);
 
 /* enable this to stress test the chip's TCE cache */
 #ifdef CONFIG_IOMMU_DEBUG
-static inline void tce_cache_blast_stress(struct iommu_table *tbl)
+int debugging __read_mostly = 1;
+
+static inline unsigned long verify_bit_range(unsigned long* bitmap,
+       int expected, unsigned long start, unsigned long end)
 {
-       tce_cache_blast(tbl);
+       unsigned long idx = start;
+
+       BUG_ON(start >= end);
+
+       while (idx < end) {
+               if (!!test_bit(idx, bitmap) != expected)
+                       return idx;
+               ++idx;
+       }
+
+       /* all bits have the expected value */
+       return ~0UL;
 }
-#else
-static inline void tce_cache_blast_stress(struct iommu_table *tbl)
+#else /* debugging is disabled */
+int debugging __read_mostly = 0;
+
+static inline unsigned long verify_bit_range(unsigned long* bitmap,
+       int expected, unsigned long start, unsigned long end)
 {
+       return ~0UL;
 }
-#endif /* BLAST_TCE_CACHE_ON_UNMAP */
+#endif /* CONFIG_IOMMU_DEBUG */
 
 static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen)
 {
@@ -149,7 +168,7 @@ static inline unsigned int num_dma_pages(unsigned long dma, unsigned int dmalen)
 
 static inline int translate_phb(struct pci_dev* dev)
 {
-       int disabled = test_bit(dev->bus->number, translation_disabled);
+       int disabled = bus_info[dev->bus->number].translation_disabled;
        return !disabled;
 }
 
@@ -158,6 +177,7 @@ static void iommu_range_reserve(struct iommu_table *tbl,
 {
        unsigned long index;
        unsigned long end;
+       unsigned long badbit;
 
        index = start_addr >> PAGE_SHIFT;
 
@@ -169,14 +189,15 @@ static void iommu_range_reserve(struct iommu_table *tbl,
        if (end > tbl->it_size) /* don't go off the table */
                end = tbl->it_size;
 
-       while (index < end) {
-               if (test_bit(index, tbl->it_map))
+       badbit = verify_bit_range(tbl->it_map, 0, index, end);
+       if (badbit != ~0UL) {
+               if (printk_ratelimit())
                        printk(KERN_ERR "Calgary: entry already allocated at "
                               "0x%lx tbl %p dma 0x%lx npages %u\n",
-                              index, tbl, start_addr, npages);
-               ++index;
+                              badbit, tbl, start_addr, npages);
        }
-       set_bit_string(tbl->it_map, start_addr >> PAGE_SHIFT, npages);
+
+       set_bit_string(tbl->it_map, index, npages);
 }
 
 static unsigned long iommu_range_alloc(struct iommu_table *tbl,
@@ -243,7 +264,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
        unsigned int npages)
 {
        unsigned long entry;
-       unsigned long i;
+       unsigned long badbit;
 
        entry = dma_addr >> PAGE_SHIFT;
 
@@ -251,16 +272,15 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
 
        tce_free(tbl, entry, npages);
 
-       for (i = 0; i < npages; ++i) {
-               if (!test_bit(entry + i, tbl->it_map))
+       badbit = verify_bit_range(tbl->it_map, 1, entry, entry + npages);
+       if (badbit != ~0UL) {
+               if (printk_ratelimit())
                        printk(KERN_ERR "Calgary: bit is off at 0x%lx "
                               "tbl %p dma 0x%Lx entry 0x%lx npages %u\n",
-                              entry + i, tbl, dma_addr, entry, npages);
+                              badbit, tbl, dma_addr, entry, npages);
        }
 
        __clear_bit_string(tbl->it_map, entry, npages);
-
-       tce_cache_blast_stress(tbl);
 }
 
 static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
@@ -454,7 +474,7 @@ static struct dma_mapping_ops calgary_dma_ops = {
 
 static inline int busno_to_phbid(unsigned char num)
 {
-       return bus_to_phb[num];
+       return bus_info[num].phbid;
 }
 
 static inline unsigned long split_queue_offset(unsigned char num)
@@ -631,6 +651,10 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar)
        if (ret)
                return ret;
 
+       tbl = dev->sysdata;
+       tbl->it_base = (unsigned long)bus_info[dev->bus->number].tce_space;
+       tce_free(tbl, 0, tbl->it_size);
+
        calgary_reserve_regions(dev);
 
        /* set TARs for each PHB */
@@ -654,11 +678,12 @@ static int __init calgary_setup_tar(struct pci_dev *dev, void __iomem *bbar)
        return 0;
 }
 
-static void __init calgary_free_tar(struct pci_dev *dev)
+static void __init calgary_free_bus(struct pci_dev *dev)
 {
        u64 val64;
        struct iommu_table *tbl = dev->sysdata;
        void __iomem *target;
+       unsigned int bitmapsz;
 
        target = calgary_reg(tbl->bbar, tar_offset(dev->bus->number));
        val64 = be64_to_cpu(readq(target));
@@ -666,8 +691,15 @@ static void __init calgary_free_tar(struct pci_dev *dev)
        writeq(cpu_to_be64(val64), target);
        readq(target); /* flush */
 
+       bitmapsz = tbl->it_size / BITS_PER_BYTE;
+       free_pages((unsigned long)tbl->it_map, get_order(bitmapsz));
+       tbl->it_map = NULL;
+
        kfree(tbl);
        dev->sysdata = NULL;
+
+       /* Can't free bootmem allocated memory after system is up :-( */
+       bus_info[dev->bus->number].tce_space = NULL;
 }
 
 static void calgary_watchdog(unsigned long data)
@@ -772,12 +804,11 @@ static inline unsigned int __init locate_register_space(struct pci_dev *dev)
        return address;
 }
 
-static int __init calgary_init_one_nontraslated(struct pci_dev *dev)
+static void __init calgary_init_one_nontraslated(struct pci_dev *dev)
 {
+       pci_dev_get(dev);
        dev->sysdata = NULL;
        dev->bus->self = dev;
-
-       return 0;
 }
 
 static int __init calgary_init_one(struct pci_dev *dev)
@@ -798,6 +829,7 @@ static int __init calgary_init_one(struct pci_dev *dev)
        if (ret)
                goto iounmap;
 
+       pci_dev_get(dev);
        dev->bus->self = dev;
        calgary_enable_translation(dev);
 
@@ -824,10 +856,9 @@ static int __init calgary_init(void)
                        calgary_init_one_nontraslated(dev);
                        continue;
                }
-               if (!tce_table_kva[dev->bus->number] && !translate_empty_slots) {
-                       pci_dev_put(dev);
+               if (!bus_info[dev->bus->number].tce_space && !translate_empty_slots)
                        continue;
-               }
+
                ret = calgary_init_one(dev);
                if (ret)
                        goto error;
@@ -840,15 +871,18 @@ error:
                dev = pci_find_device_reverse(PCI_VENDOR_ID_IBM,
                                              PCI_DEVICE_ID_IBM_CALGARY,
                                              dev);
+               if (!dev)
+                       break;
                if (!translate_phb(dev)) {
                        pci_dev_put(dev);
                        continue;
                }
-               if (!tce_table_kva[dev->bus->number] && !translate_empty_slots)
+               if (!bus_info[dev->bus->number].tce_space && !translate_empty_slots)
                        continue;
+
                calgary_disable_translation(dev);
-               calgary_free_tar(dev);
-               pci_dev_put(dev);
+               calgary_free_bus(dev);
+               pci_dev_put(dev); /* Undo calgary_init_one()'s pci_dev_get() */
        }
 
        return ret;
@@ -890,13 +924,15 @@ void __init detect_calgary(void)
        if (swiotlb || no_iommu || iommu_detected)
                return;
 
+       if (!early_pci_allowed())
+               return;
+
        specified_table_size = determine_tce_table_size(end_pfn * PAGE_SIZE);
 
        for (bus = 0; bus < MAX_PHB_BUS_NUM; bus++) {
                int dev;
-
-               tce_table_kva[bus] = NULL;
-               bus_to_phb[bus] = -1;
+               struct calgary_bus_info *info = &bus_info[bus];
+               info->phbid = -1;
 
                if (read_pci_config(bus, 0, 0, 0) != PCI_VENDOR_DEVICE_ID_CALGARY)
                        continue;
@@ -907,12 +943,9 @@ void __init detect_calgary(void)
                 */
                phb = (phb + 1) % PHBS_PER_CALGARY;
 
-               if (test_bit(bus, translation_disabled)) {
-                       printk(KERN_INFO "Calgary: translation is disabled for "
-                              "PHB 0x%x\n", bus);
-                       /* skip this phb, don't allocate a tbl for it */
+               if (info->translation_disabled)
                        continue;
-               }
+
                /*
                 * Scan the slots of the PCI bus to see if there is a device present.
                 * The parent bus will be the zero-ith device, so start at 1.
@@ -923,8 +956,8 @@ void __init detect_calgary(void)
                                tbl = alloc_tce_table();
                                if (!tbl)
                                        goto cleanup;
-                               tce_table_kva[bus] = tbl;
-                               bus_to_phb[bus] = phb;
+                               info->tce_space = tbl;
+                               info->phbid = phb;
                                calgary_found = 1;
                                break;
                        }
@@ -934,15 +967,20 @@ void __init detect_calgary(void)
        if (calgary_found) {
                iommu_detected = 1;
                calgary_detected = 1;
-               printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected. "
-                      "TCE table spec is %d.\n", specified_table_size);
+               printk(KERN_INFO "PCI-DMA: Calgary IOMMU detected.\n");
+               printk(KERN_INFO "PCI-DMA: Calgary TCE table spec is %d, "
+                      "CONFIG_IOMMU_DEBUG is %s.\n", specified_table_size,
+                      debugging ? "enabled" : "disabled");
        }
        return;
 
 cleanup:
-       for (--bus; bus >= 0; --bus)
-               if (tce_table_kva[bus])
-                       free_tce_table(tce_table_kva[bus]);
+       for (--bus; bus >= 0; --bus) {
+               struct calgary_bus_info *info = &bus_info[bus];
+
+               if (info->tce_space)
+                       free_tce_table(info->tce_space);
+       }
 }
 
 int __init calgary_iommu_init(void)
@@ -1016,7 +1054,7 @@ static int __init calgary_parse_options(char *p)
                        if (bridge < MAX_PHB_BUS_NUM) {
                                printk(KERN_INFO "Calgary: disabling "
                                       "translation for PHB 0x%x\n", bridge);
-                               set_bit(bridge, translation_disabled);
+                               bus_info[bridge].translation_disabled = 1;
                        }
                }
 
index 9c44f4f2433d7b4d77ed1ee9e2192f14b0149228..4dcb671bd19fa760f81dc7d22f05a3eecf7c36a4 100644 (file)
@@ -236,6 +236,9 @@ __init int iommu_setup(char *p)
 {
     iommu_merge = 1;
 
+       if (!p)
+               return -EINVAL;
+
     while (*p) {
            if (!strncmp(p,"off",3))
                    no_iommu = 1;
@@ -278,9 +281,9 @@ __init int iommu_setup(char *p)
            if (*p == ',')
                    ++p;
     }
-    return 1;
+    return 0;
 }
-__setup("iommu=", iommu_setup);
+early_param("iommu", iommu_setup);
 
 void __init pci_iommu_alloc(void)
 {
index 6d3e61baf7a0159c015f4b439d88fe404dcb129a..16261a8a3303ed044fba4b31eb612a9f9c3454aa 100644 (file)
@@ -239,8 +239,6 @@ dma_addr_t gart_map_single(struct device *dev, void *addr, size_t size, int dir)
 {
        unsigned long phys_mem, bus;
 
-       BUG_ON(dir == DMA_NONE);
-
        if (!dev)
                dev = &fallback_dev;
 
@@ -383,7 +381,6 @@ int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir)
        unsigned long pages = 0;
        int need = 0, nextneed;
 
-       BUG_ON(dir == DMA_NONE);
        if (nents == 0) 
                return 0;
 
index aad7609d8e9249e6d9121128e723838a4e508da6..df09ab05a1bd1efbb931d893a4f174f6f00ac651 100644 (file)
@@ -59,7 +59,6 @@ int nommu_map_sg(struct device *hwdev, struct scatterlist *sg,
 {
        int i;
 
-       BUG_ON(direction == DMA_NONE);
        for (i = 0; i < nents; i++ ) {
                struct scatterlist *s = &sg[i];
                BUG_ON(!s->page);
index bb6745d13b8ff5f3bb1b59d32e50716d910c7c39..458006ae19f3837c240477611cdcb6c1e3df503f 100644 (file)
@@ -80,25 +80,25 @@ void idle_notifier_unregister(struct notifier_block *n)
 }
 EXPORT_SYMBOL(idle_notifier_unregister);
 
-enum idle_state { CPU_IDLE, CPU_NOT_IDLE };
-static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE;
-
 void enter_idle(void)
 {
-       __get_cpu_var(idle_state) = CPU_IDLE;
+       write_pda(isidle, 1);
        atomic_notifier_call_chain(&idle_notifier, IDLE_START, NULL);
 }
 
 static void __exit_idle(void)
 {
-       __get_cpu_var(idle_state) = CPU_NOT_IDLE;
+       if (read_pda(isidle) == 0)
+               return;
+       write_pda(isidle, 0);
        atomic_notifier_call_chain(&idle_notifier, IDLE_END, NULL);
 }
 
 /* Called from interrupts to signify idle end */
 void exit_idle(void)
 {
-       if (current->pid | read_pda(irqcount))
+       /* idle loop has pid 0 */
+       if (current->pid)
                return;
        __exit_idle();
 }
@@ -220,6 +220,9 @@ void cpu_idle (void)
                                play_dead();
                        enter_idle();
                        idle();
+                       /* In many cases the interrupt that ended idle
+                          has already called exit_idle. But some idle
+                          loops can be woken up without interrupt. */
                        __exit_idle();
                }
 
@@ -350,6 +353,7 @@ void exit_thread(void)
 
                kfree(t->io_bitmap_ptr);
                t->io_bitmap_ptr = NULL;
+               clear_thread_flag(TIF_IO_BITMAP);
                /*
                 * Careful, clear this in the TSS too:
                 */
@@ -369,6 +373,7 @@ void flush_thread(void)
                if (t->flags & _TIF_IA32)
                        current_thread_info()->status |= TS_COMPAT;
        }
+       t->flags &= ~_TIF_DEBUG;
 
        tsk->thread.debugreg0 = 0;
        tsk->thread.debugreg1 = 0;
@@ -461,7 +466,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
        asm("mov %%es,%0" : "=m" (p->thread.es));
        asm("mov %%ds,%0" : "=m" (p->thread.ds));
 
-       if (unlikely(me->thread.io_bitmap_ptr != NULL)) { 
+       if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
                p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
                if (!p->thread.io_bitmap_ptr) {
                        p->thread.io_bitmap_max = 0;
@@ -469,6 +474,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
                }
                memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr,
                                IO_BITMAP_BYTES);
+               set_tsk_thread_flag(p, TIF_IO_BITMAP);
        } 
 
        /*
@@ -498,6 +504,40 @@ out:
  */
 #define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r)
 
+static inline void __switch_to_xtra(struct task_struct *prev_p,
+                                   struct task_struct *next_p,
+                                   struct tss_struct *tss)
+{
+       struct thread_struct *prev, *next;
+
+       prev = &prev_p->thread,
+       next = &next_p->thread;
+
+       if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
+               loaddebug(next, 0);
+               loaddebug(next, 1);
+               loaddebug(next, 2);
+               loaddebug(next, 3);
+               /* no 4 and 5 */
+               loaddebug(next, 6);
+               loaddebug(next, 7);
+       }
+
+       if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
+               /*
+                * Copy the relevant range of the IO bitmap.
+                * Normally this is 128 bytes or less:
+                */
+               memcpy(tss->io_bitmap, next->io_bitmap_ptr,
+                      max(prev->io_bitmap_max, next->io_bitmap_max));
+       } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) {
+               /*
+                * Clear any possible leftover bits:
+                */
+               memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
+       }
+}
+
 /*
  *     switch_to(x,y) should switch tasks from x to y.
  *
@@ -515,6 +555,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        int cpu = smp_processor_id();  
        struct tss_struct *tss = &per_cpu(init_tss, cpu);
 
+       /* we're going to use this soon, after a few expensive things */
+       if (next_p->fpu_counter>5)
+               prefetch(&next->i387.fxsave);
+
        /*
         * Reload esp0, LDT and the page table pointer:
         */
@@ -583,41 +627,29 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
           And the AMD workaround requires it to be after DS reload. */
        unlazy_fpu(prev_p);
        write_pda(kernelstack,
-                 task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
-
+       (unsigned long)task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
+#ifdef CONFIG_CC_STACKPROTECTOR
+       write_pda(stack_canary, next_p->stack_canary);
        /*
-        * Now maybe reload the debug registers
+        * Build time only check to make sure the stack_canary is at
+        * offset 40 in the pda; this is a gcc ABI requirement
         */
-       if (unlikely(next->debugreg7)) {
-               loaddebug(next, 0);
-               loaddebug(next, 1);
-               loaddebug(next, 2);
-               loaddebug(next, 3);
-               /* no 4 and 5 */
-               loaddebug(next, 6);
-               loaddebug(next, 7);
-       }
-
+       BUILD_BUG_ON(offsetof(struct x8664_pda, stack_canary) != 40);
+#endif
 
-       /* 
-        * Handle the IO bitmap 
-        */ 
-       if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
-               if (next->io_bitmap_ptr)
-                       /*
-                        * Copy the relevant range of the IO bitmap.
-                        * Normally this is 128 bytes or less:
-                        */
-                       memcpy(tss->io_bitmap, next->io_bitmap_ptr,
-                               max(prev->io_bitmap_max, next->io_bitmap_max));
-               else {
-                       /*
-                        * Clear any possible leftover bits:
-                        */
-                       memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
-               }
-       }
+       /*
+        * Now maybe reload the debug registers and handle I/O bitmaps
+        */
+       if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
+           || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))
+               __switch_to_xtra(prev_p, next_p, tss);
 
+       /* 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
+        */
+       if (next_p->fpu_counter>5)
+               math_state_restore();
        return prev_p;
 }
 
@@ -834,7 +866,7 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
 
 unsigned long arch_align_stack(unsigned long sp)
 {
-       if (randomize_va_space)
+       if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
                sp -= get_random_int() % 8192;
        return sp & ~0xf;
 }
index 2d50024c9f308b8fb5f390fb46e88d33bc843d3d..addc14af0c562a7ec485c89fc6c69d71bb3ed1ca 100644 (file)
@@ -116,17 +116,17 @@ unsigned long convert_rip_to_linear(struct task_struct *child, struct pt_regs *r
        return addr;
 }
 
-static int is_at_popf(struct task_struct *child, struct pt_regs *regs)
+static int is_setting_trap_flag(struct task_struct *child, struct pt_regs *regs)
 {
        int i, copied;
-       unsigned char opcode[16];
+       unsigned char opcode[15];
        unsigned long addr = convert_rip_to_linear(child, regs);
 
        copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0);
        for (i = 0; i < copied; i++) {
                switch (opcode[i]) {
-               /* popf */
-               case 0x9d:
+               /* popf and iret */
+               case 0x9d: case 0xcf:
                        return 1;
 
                        /* CHECKME: 64 65 */
@@ -138,14 +138,17 @@ static int is_at_popf(struct task_struct *child, struct pt_regs *regs)
                case 0x26: case 0x2e:
                case 0x36: case 0x3e:
                case 0x64: case 0x65:
-               case 0xf0: case 0xf2: case 0xf3:
+               case 0xf2: case 0xf3:
                        continue;
 
-               /* REX prefixes */
                case 0x40 ... 0x4f:
+                       if (regs->cs != __USER_CS)
+                               /* 32-bit mode: register increment */
+                               return 0;
+                       /* 64-bit mode: REX prefix */
                        continue;
 
-                       /* CHECKME: f0, f2, f3 */
+                       /* CHECKME: f2, f3 */
 
                /*
                 * pushf: NOTE! We should probably not let
@@ -186,10 +189,8 @@ static void set_singlestep(struct task_struct *child)
         * ..but if TF is changed by the instruction we will trace,
         * don't mark it as being "us" that set it, so that we
         * won't clear it by hand later.
-        *
-        * AK: this is not enough, LAHF and IRET can change TF in user space too.
         */
-       if (is_at_popf(child, regs))
+       if (is_setting_trap_flag(child, regs))
                return;
 
        child->ptrace |= PT_DTRACE;
@@ -420,9 +421,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                                if ((0x5554 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
                                        break;
                        if (i == 4) {
-                               child->thread.debugreg7 = data;
+                         child->thread.debugreg7 = data;
+                         if (data)
+                               set_tsk_thread_flag(child, TIF_DEBUG);
+                         else
+                               clear_tsk_thread_flag(child, TIF_DEBUG);
                          ret = 0;
-                 }
+                       }
                  break;
                }
                break;
index d24fa9b72a2bc8856a4d6adcf556d091f69594e0..14e95872c6a3aef01c32889d5a78586c2c0780f4 100644 (file)
  */
 
 #include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/kexec.h>
 
-       /*
-        * Must be relocatable PIC code callable as a C function, that once
-        * it starts can not use the previous processes stack.
-        */
-       .globl relocate_new_kernel
+/*
+ * Must be relocatable PIC code callable as a C function
+ */
+
+#define PTR(x) (x << 3)
+#define PAGE_ALIGNED (1 << PAGE_SHIFT)
+#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */
+
+       .text
+       .align PAGE_ALIGNED
        .code64
+       .globl relocate_kernel
+relocate_kernel:
+       /* %rdi indirection_page
+        * %rsi page_list
+        * %rdx start address
+        */
+
+       /* map the control page at its virtual address */
+
+       movq    $0x0000ff8000000000, %r10        /* mask */
+       mov     $(39 - 3), %cl                   /* bits to shift */
+       movq    PTR(VA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
+
+       movq    %r11, %r9
+       andq    %r10, %r9
+       shrq    %cl, %r9
+
+       movq    PTR(VA_PGD)(%rsi), %r8
+       addq    %r8, %r9
+       movq    PTR(PA_PUD_0)(%rsi), %r8
+       orq     $PAGE_ATTR, %r8
+       movq    %r8, (%r9)
+
+       shrq    $9, %r10
+       sub     $9, %cl
+
+       movq    %r11, %r9
+       andq    %r10, %r9
+       shrq    %cl, %r9
+
+       movq    PTR(VA_PUD_0)(%rsi), %r8
+       addq    %r8, %r9
+       movq    PTR(PA_PMD_0)(%rsi), %r8
+       orq     $PAGE_ATTR, %r8
+       movq    %r8, (%r9)
+
+       shrq    $9, %r10
+       sub     $9, %cl
+
+       movq    %r11, %r9
+       andq    %r10, %r9
+       shrq    %cl, %r9
+
+       movq    PTR(VA_PMD_0)(%rsi), %r8
+       addq    %r8, %r9
+       movq    PTR(PA_PTE_0)(%rsi), %r8
+       orq     $PAGE_ATTR, %r8
+       movq    %r8, (%r9)
+
+       shrq    $9, %r10
+       sub     $9, %cl
+
+       movq    %r11, %r9
+       andq    %r10, %r9
+       shrq    %cl, %r9
+
+       movq    PTR(VA_PTE_0)(%rsi), %r8
+       addq    %r8, %r9
+       movq    PTR(PA_CONTROL_PAGE)(%rsi), %r8
+       orq     $PAGE_ATTR, %r8
+       movq    %r8, (%r9)
+
+       /* identity map the control page at its physical address */
+
+       movq    $0x0000ff8000000000, %r10        /* mask */
+       mov     $(39 - 3), %cl                   /* bits to shift */
+       movq    PTR(PA_CONTROL_PAGE)(%rsi), %r11 /* address to map */
+
+       movq    %r11, %r9
+       andq    %r10, %r9
+       shrq    %cl, %r9
+
+       movq    PTR(VA_PGD)(%rsi), %r8
+       addq    %r8, %r9
+       movq    PTR(PA_PUD_1)(%rsi), %r8
+       orq     $PAGE_ATTR, %r8
+       movq    %r8, (%r9)
+
+       shrq    $9, %r10
+       sub     $9, %cl
+
+       movq    %r11, %r9
+       andq    %r10, %r9
+       shrq    %cl, %r9
+
+       movq    PTR(VA_PUD_1)(%rsi), %r8
+       addq    %r8, %r9
+       movq    PTR(PA_PMD_1)(%rsi), %r8
+       orq     $PAGE_ATTR, %r8
+       movq    %r8, (%r9)
+
+       shrq    $9, %r10
+       sub     $9, %cl
+
+       movq    %r11, %r9
+       andq    %r10, %r9
+       shrq    %cl, %r9
+
+       movq    PTR(VA_PMD_1)(%rsi), %r8
+       addq    %r8, %r9
+       movq    PTR(PA_PTE_1)(%rsi), %r8
+       orq     $PAGE_ATTR, %r8
+       movq    %r8, (%r9)
+
+       shrq    $9, %r10
+       sub     $9, %cl
+
+       movq    %r11, %r9
+       andq    %r10, %r9
+       shrq    %cl, %r9
+
+       movq    PTR(VA_PTE_1)(%rsi), %r8
+       addq    %r8, %r9
+       movq    PTR(PA_CONTROL_PAGE)(%rsi), %r8
+       orq     $PAGE_ATTR, %r8
+       movq    %r8, (%r9)
+
 relocate_new_kernel:
-       /* %rdi page_list
-        * %rsi reboot_code_buffer
+       /* %rdi indirection_page
+        * %rsi page_list
         * %rdx start address
-        * %rcx page_table
-        * %r8  arg5
-        * %r9  arg6
         */
 
        /* zero out flags, and disable interrupts */
        pushq $0
        popfq
 
-       /* set a new stack at the bottom of our page... */
-       lea   4096(%rsi), %rsp
+       /* get physical address of control page now */
+       /* this is impossible after page table switch */
+       movq    PTR(PA_CONTROL_PAGE)(%rsi), %r8
+
+       /* get physical address of page table now too */
+       movq    PTR(PA_TABLE_PAGE)(%rsi), %rcx
 
-       /* store the parameters back on the stack */
-       pushq   %rdx /* store the start address */
+       /* switch to new set of page tables */
+       movq    PTR(PA_PGD)(%rsi), %r9
+       movq    %r9, %cr3
+
+       /* setup a new stack at the end of the physical control page */
+       lea     4096(%r8), %rsp
+
+       /* jump to identity mapped page */
+       addq    $(identity_mapped - relocate_kernel), %r8
+       pushq   %r8
+       ret
+
+identity_mapped:
+       /* store the start address on the stack */
+       pushq   %rdx
 
        /* Set cr0 to a known state:
         * 31 1 == Paging enabled
@@ -136,8 +274,3 @@ relocate_new_kernel:
        xorq    %r15, %r15
 
        ret
-relocate_new_kernel_end:
-
-       .globl relocate_new_kernel_size
-relocate_new_kernel_size:
-       .quad relocate_new_kernel_end - relocate_new_kernel
index 4b39f0da17f3d3f56795233aa4745b42f652ca79..0b00bb2ea5766fde600c537f4bc2778d33b9b1e0 100644 (file)
@@ -74,16 +74,6 @@ EXPORT_SYMBOL(boot_cpu_data);
 
 unsigned long mmu_cr4_features;
 
-int acpi_disabled;
-EXPORT_SYMBOL(acpi_disabled);
-#ifdef CONFIG_ACPI
-extern int __initdata acpi_ht;
-extern acpi_interrupt_flags    acpi_sci_flags;
-int __initdata acpi_force = 0;
-#endif
-
-int acpi_numa __initdata;
-
 /* Boot loader ID as an integer, for the benefit of proc_dointvec */
 int bootloader_type;
 
@@ -107,7 +97,6 @@ struct sys_desc_table_struct {
 
 struct edid_info edid_info;
 EXPORT_SYMBOL_GPL(edid_info);
-struct e820map e820;
 
 extern int root_mountflags;
 
@@ -276,185 +265,22 @@ static void __init probe_roms(void)
        }
 }
 
-/* Check for full argument with no trailing characters */
-static int fullarg(char *p, char *arg)
+#ifdef CONFIG_PROC_VMCORE
+/* elfcorehdr= specifies the location of elf core header
+ * stored by the crashed kernel. This option will be passed
+ * by kexec loader to the capture kernel.
+ */
+static int __init setup_elfcorehdr(char *arg)
 {
-       int l = strlen(arg);
-       return !memcmp(p, arg, l) && (p[l] == 0 || isspace(p[l]));
+       char *end;
+       if (!arg)
+               return -EINVAL;
+       elfcorehdr_addr = memparse(arg, &end);
+       return end > arg ? 0 : -EINVAL;
 }
-
-static __init void parse_cmdline_early (char ** cmdline_p)
-{
-       char c = ' ', *to = command_line, *from = COMMAND_LINE;
-       int len = 0;
-       int userdef = 0;
-
-       for (;;) {
-               if (c != ' ') 
-                       goto next_char; 
-
-#ifdef  CONFIG_SMP
-               /*
-                * If the BIOS enumerates physical processors before logical,
-                * maxcpus=N at enumeration-time can be used to disable HT.
-                */
-               else if (!memcmp(from, "maxcpus=", 8)) {
-                       extern unsigned int maxcpus;
-
-                       maxcpus = simple_strtoul(from + 8, NULL, 0);
-               }
-#endif
-#ifdef CONFIG_ACPI
-               /* "acpi=off" disables both ACPI table parsing and interpreter init */
-               if (fullarg(from,"acpi=off"))
-                       disable_acpi();
-
-               if (fullarg(from, "acpi=force")) { 
-                       /* add later when we do DMI horrors: */
-                       acpi_force = 1;
-                       acpi_disabled = 0;
-               }
-
-               /* acpi=ht just means: do ACPI MADT parsing 
-                  at bootup, but don't enable the full ACPI interpreter */
-               if (fullarg(from, "acpi=ht")) { 
-                       if (!acpi_force)
-                               disable_acpi();
-                       acpi_ht = 1; 
-               }
-                else if (fullarg(from, "pci=noacpi")) 
-                       acpi_disable_pci();
-               else if (fullarg(from, "acpi=noirq"))
-                       acpi_noirq_set();
-
-               else if (fullarg(from, "acpi_sci=edge"))
-                       acpi_sci_flags.trigger =  1;
-               else if (fullarg(from, "acpi_sci=level"))
-                       acpi_sci_flags.trigger = 3;
-               else if (fullarg(from, "acpi_sci=high"))
-                       acpi_sci_flags.polarity = 1;
-               else if (fullarg(from, "acpi_sci=low"))
-                       acpi_sci_flags.polarity = 3;
-
-               /* acpi=strict disables out-of-spec workarounds */
-               else if (fullarg(from, "acpi=strict")) {
-                       acpi_strict = 1;
-               }
-#ifdef CONFIG_X86_IO_APIC
-               else if (fullarg(from, "acpi_skip_timer_override"))
-                       acpi_skip_timer_override = 1;
-#endif
-#endif
-
-               if (fullarg(from, "disable_timer_pin_1"))
-                       disable_timer_pin_1 = 1;
-               if (fullarg(from, "enable_timer_pin_1"))
-                       disable_timer_pin_1 = -1;
-
-               if (fullarg(from, "nolapic") || fullarg(from, "disableapic")) {
-                       clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-                       disable_apic = 1;
-               }
-
-               if (fullarg(from, "noapic"))
-                       skip_ioapic_setup = 1;
-
-               if (fullarg(from,"apic")) {
-                       skip_ioapic_setup = 0;
-                       ioapic_force = 1;
-               }
-                       
-               if (!memcmp(from, "mem=", 4))
-                       parse_memopt(from+4, &from); 
-
-               if (!memcmp(from, "memmap=", 7)) {
-                       /* exactmap option is for used defined memory */
-                       if (!memcmp(from+7, "exactmap", 8)) {
-#ifdef CONFIG_CRASH_DUMP
-                               /* If we are doing a crash dump, we
-                                * still need to know the real mem
-                                * size before original memory map is
-                                * reset.
-                                */
-                               saved_max_pfn = e820_end_of_ram();
-#endif
-                               from += 8+7;
-                               end_pfn_map = 0;
-                               e820.nr_map = 0;
-                               userdef = 1;
-                       }
-                       else {
-                               parse_memmapopt(from+7, &from);
-                               userdef = 1;
-                       }
-               }
-
-#ifdef CONFIG_NUMA
-               if (!memcmp(from, "numa=", 5))
-                       numa_setup(from+5); 
+early_param("elfcorehdr", setup_elfcorehdr);
 #endif
 
-               if (!memcmp(from,"iommu=",6)) { 
-                       iommu_setup(from+6); 
-               }
-
-               if (fullarg(from,"oops=panic"))
-                       panic_on_oops = 1;
-
-               if (!memcmp(from, "noexec=", 7))
-                       nonx_setup(from + 7);
-
-#ifdef CONFIG_KEXEC
-               /* crashkernel=size@addr specifies the location to reserve for
-                * a crash kernel.  By reserving this memory we guarantee
-                * that linux never set's it up as a DMA target.
-                * Useful for holding code to do something appropriate
-                * after a kernel panic.
-                */
-               else if (!memcmp(from, "crashkernel=", 12)) {
-                       unsigned long size, base;
-                       size = memparse(from+12, &from);
-                       if (*from == '@') {
-                               base = memparse(from+1, &from);
-                               /* FIXME: Do I want a sanity check
-                                * to validate the memory range?
-                                */
-                               crashk_res.start = base;
-                               crashk_res.end   = base + size - 1;
-                       }
-               }
-#endif
-
-#ifdef CONFIG_PROC_VMCORE
-               /* elfcorehdr= specifies the location of elf core header
-                * stored by the crashed kernel. This option will be passed
-                * by kexec loader to the capture kernel.
-                */
-               else if(!memcmp(from, "elfcorehdr=", 11))
-                       elfcorehdr_addr = memparse(from+11, &from);
-#endif
-
-#ifdef CONFIG_HOTPLUG_CPU
-               else if (!memcmp(from, "additional_cpus=", 16))
-                       setup_additional_cpus(from+16);
-#endif
-
-       next_char:
-               c = *(from++);
-               if (!c)
-                       break;
-               if (COMMAND_LINE_SIZE <= ++len)
-                       break;
-               *(to++) = c;
-       }
-       if (userdef) {
-               printk(KERN_INFO "user-defined physical RAM map:\n");
-               e820_print_map("user");
-       }
-       *to = '\0';
-       *cmdline_p = command_line;
-}
-
 #ifndef CONFIG_NUMA
 static void __init
 contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
@@ -466,7 +292,8 @@ contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
        if (bootmap == -1L)
                panic("Cannot find bootmem map of size %ld\n",bootmap_size);
        bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
-       e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
+       e820_register_active_regions(0, start_pfn, end_pfn);
+       free_bootmem_with_active_regions(0, end_pfn);
        reserve_bootmem(bootmap, bootmap_size);
 } 
 #endif
@@ -521,6 +348,8 @@ static void discover_ebda(void)
 
 void __init setup_arch(char **cmdline_p)
 {
+       printk(KERN_INFO "Command line: %s\n", saved_command_line);
+
        ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV);
        screen_info = SCREEN_INFO;
        edid_info = EDID_INFO;
@@ -547,16 +376,22 @@ void __init setup_arch(char **cmdline_p)
        data_resource.start = virt_to_phys(&_etext);
        data_resource.end = virt_to_phys(&_edata)-1;
 
-       parse_cmdline_early(cmdline_p);
-
        early_identify_cpu(&boot_cpu_data);
 
+       strlcpy(command_line, saved_command_line, COMMAND_LINE_SIZE);
+       *cmdline_p = command_line;
+
+       parse_early_param();
+
+       finish_e820_parsing();
+
+       e820_register_active_regions(0, 0, -1UL);
        /*
         * partially used pages are not usable - thus
         * we are rounding upwards:
         */
        end_pfn = e820_end_of_ram();
-       num_physpages = end_pfn;                /* for pfn_valid */
+       num_physpages = end_pfn;
 
        check_efer();
 
@@ -576,6 +411,14 @@ void __init setup_arch(char **cmdline_p)
        acpi_boot_table_init();
 #endif
 
+       /* How many end-of-memory variables you have, grandma! */
+       max_low_pfn = end_pfn;
+       max_pfn = end_pfn;
+       high_memory = (void *)__va(end_pfn * PAGE_SIZE - 1) + 1;
+
+       /* Remove active ranges so rediscovery with NUMA-awareness happens */
+       remove_all_active_ranges();
+
 #ifdef CONFIG_ACPI_NUMA
        /*
         * Parse SRAT to discover nodes.
@@ -625,12 +468,10 @@ void __init setup_arch(char **cmdline_p)
         */
        acpi_reserve_bootmem();
 #endif
-#ifdef CONFIG_X86_LOCAL_APIC
        /*
         * Find and reserve possible boot-time SMP configuration:
         */
        find_smp_config();
-#endif
 #ifdef CONFIG_BLK_DEV_INITRD
        if (LOADER_TYPE && INITRD_START) {
                if (INITRD_START + INITRD_SIZE <= (end_pfn << PAGE_SHIFT)) {
@@ -657,7 +498,9 @@ void __init setup_arch(char **cmdline_p)
 
        paging_init();
 
-       check_ioapic();
+#ifdef CONFIG_PCI
+       early_quirks();
+#endif
 
        /*
         * set this early, so we dont allocate cpu0
@@ -674,14 +517,12 @@ void __init setup_arch(char **cmdline_p)
 
        init_cpu_to_node();
 
-#ifdef CONFIG_X86_LOCAL_APIC
        /*
         * get boot-time SMP configuration:
         */
        if (smp_found_config)
                get_smp_config();
        init_apic_mappings();
-#endif
 
        /*
         * Request address space for all standard RAM and ROM resources
@@ -839,7 +680,7 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
 #endif
 }
 
-static void __init init_amd(struct cpuinfo_x86 *c)
+static void __cpuinit init_amd(struct cpuinfo_x86 *c)
 {
        unsigned level;
 
@@ -895,6 +736,12 @@ static void __init init_amd(struct cpuinfo_x86 *c)
 
        /* Fix cpuid4 emulation for more */
        num_cache_leaves = 3;
+
+       /* When there is only one core no need to synchronize RDTSC */
+       if (num_possible_cpus() == 1)
+               set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
+       else
+               clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
 }
 
 static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
@@ -976,8 +823,7 @@ static void srat_detect_node(void)
                node = first_node(node_online_map);
        numa_set_node(cpu, node);
 
-       if (acpi_numa > 0)
-               printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
+       printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
 #endif
 }
 
@@ -1011,6 +857,8 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
        if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
            (c->x86 == 0x6 && c->x86_model >= 0x0e))
                set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability);
+       if (c->x86 == 6)
+               set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
        set_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability);
        c->x86_max_cores = intel_num_cpu_cores(c);
 
@@ -1229,8 +1077,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
                /* Intel-defined (#2) */
                "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
-               "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL,
-               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+               "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
+               NULL, NULL, "dca", NULL, NULL, NULL, NULL, NULL,
                NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
                /* VIA/Cyrix/Centaur-defined */
index 417de564456e23baead28629aeeb2a218c8bee4b..8c4b80fe71a146c73447d4af46ced0e60d80c5b9 100644 (file)
@@ -24,7 +24,7 @@
 #include <asm/proto.h>
 #include <asm/sections.h>
 
-char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,};
+char x86_boot_params[BOOT_PARAM_SIZE] __initdata;
 
 cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
 
@@ -46,8 +46,10 @@ Control non executable mappings for 64bit processes.
 on     Enable(default)
 off    Disable
 */ 
-int __init nonx_setup(char *str)
+static int __init nonx_setup(char *str)
 {
+       if (!str)
+               return -EINVAL;
        if (!strncmp(str, "on", 2)) {
                 __supported_pte_mask |= _PAGE_NX; 
                do_not_nx = 0; 
@@ -55,9 +57,9 @@ int __init nonx_setup(char *str)
                do_not_nx = 1;
                __supported_pte_mask &= ~_PAGE_NX;
         }
-       return 1;
+       return 0;
 } 
-__setup("noexec=", nonx_setup);        /* parsed early actually */
+early_param("noexec", nonx_setup);
 
 int force_personality32 = 0; 
 
@@ -93,12 +95,9 @@ void __init setup_per_cpu_areas(void)
 #endif
 
        /* Copy section for each CPU (we discard the original) */
-       size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
-#ifdef CONFIG_MODULES
-       if (size < PERCPU_ENOUGH_ROOM)
-               size = PERCPU_ENOUGH_ROOM;
-#endif
+       size = PERCPU_ENOUGH_ROOM;
 
+       printk(KERN_INFO "PERCPU: Allocating %lu bytes of per cpu data\n", size);
        for_each_cpu_mask (i, cpu_possible_map) {
                char *ptr;
 
@@ -122,7 +121,10 @@ void pda_init(int cpu)
 
        /* Setup up data that may be needed in __get_free_pages early */
        asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0)); 
+       /* Memory clobbers used to order PDA accessed */
+       mb();
        wrmsrl(MSR_GS_BASE, pda);
+       mb();
 
        pda->cpunumber = cpu; 
        pda->irqcount = -1;
@@ -178,6 +180,8 @@ void __cpuinit check_efer(void)
         }       
 }
 
+unsigned long kernel_eflags;
+
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
  * initialized (naturally) in the bootstrap process, such as the GDT
@@ -235,28 +239,17 @@ void __cpuinit cpu_init (void)
         * set up and load the per-CPU TSS
         */
        for (v = 0; v < N_EXCEPTION_STACKS; v++) {
+               static const unsigned int order[N_EXCEPTION_STACKS] = {
+                       [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
+                       [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
+               };
                if (cpu) {
-                       static const unsigned int order[N_EXCEPTION_STACKS] = {
-                               [0 ... N_EXCEPTION_STACKS - 1] = EXCEPTION_STACK_ORDER,
-                               [DEBUG_STACK - 1] = DEBUG_STACK_ORDER
-                       };
-
                        estacks = (char *)__get_free_pages(GFP_ATOMIC, order[v]);
                        if (!estacks)
                                panic("Cannot allocate exception stack %ld %d\n",
                                      v, cpu); 
                }
-               switch (v + 1) {
-#if DEBUG_STKSZ > EXCEPTION_STKSZ
-               case DEBUG_STACK:
-                       cpu_pda(cpu)->debugstack = (unsigned long)estacks;
-                       estacks += DEBUG_STKSZ;
-                       break;
-#endif
-               default:
-                       estacks += EXCEPTION_STKSZ;
-                       break;
-               }
+               estacks += PAGE_SIZE << order[v];
                orig_ist->ist[v] = t->ist[v] = (unsigned long)estacks;
        }
 
@@ -290,4 +283,6 @@ void __cpuinit cpu_init (void)
        set_debugreg(0UL, 7);
 
        fpu_init(); 
+
+       raw_local_save_flags(kernel_eflags);
 }
index 28161170fb0aa36dcb16d91f730e83fee9d4409c..49ec324cd1411468c43af160a9ea5ec1a1ba811e 100644 (file)
@@ -37,37 +37,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 int ia32_setup_frame(int sig, struct k_sigaction *ka,
             sigset_t *set, struct pt_regs * regs); 
 
-asmlinkage long
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
-{
-       sigset_t saveset, newset;
-
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
-
-       if (copy_from_user(&newset, unewset, sizeof(newset)))
-               return -EFAULT;
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-#ifdef DEBUG_SIG
-       printk("rt_sigsuspend savset(%lx) newset(%lx) regs(%p) rip(%lx)\n",
-               saveset, newset, regs, regs->rip);
-#endif 
-       regs->rax = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(regs, &saveset))
-                       return -EINTR;
-       }
-}
-
 asmlinkage long
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
                struct pt_regs *regs)
@@ -308,11 +277,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 #endif
 
        /* Set up registers for signal handler */
-       { 
-               struct exec_domain *ed = current_thread_info()->exec_domain;
-               if (unlikely(ed && ed->signal_invmap && sig < 32))
-                       sig = ed->signal_invmap[sig];
-       } 
        regs->rdi = sig;
        /* In case the signal handler was declared without prototypes */ 
        regs->rax = 0;  
@@ -341,11 +305,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
-       return 1;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
-       return 0;
+       return -EFAULT;
 }
 
 /*
@@ -408,7 +372,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 #endif
        ret = setup_rt_frame(sig, ka, info, oldset, regs);
 
-       if (ret) {
+       if (ret == 0) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
                if (!(ka->sa.sa_flags & SA_NODEFER))
@@ -425,11 +389,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void do_signal(struct pt_regs *regs)
 {
        struct k_sigaction ka;
        siginfo_t info;
        int signr;
+       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -438,9 +403,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
         * if so.
         */
        if (!user_mode(regs))
-               return 1;
+               return;
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -454,30 +421,46 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                        set_debugreg(current->thread.debugreg7, 7);
 
                /* Whee!  Actually deliver the signal.  */
-               return handle_signal(signr, &info, &ka, oldset, regs);
+               if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+                       /* a signal was successfully delivered; the saved
+                        * sigmask will have been stored in the signal frame,
+                        * and will be restored by sigreturn, so we can simply
+                        * clear the TIF_RESTORE_SIGMASK flag */
+                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+               }
+               return;
        }
 
        /* Did we come from a system call? */
        if ((long)regs->orig_rax >= 0) {
                /* Restart the system call - no handlers present */
                long res = regs->rax;
-               if (res == -ERESTARTNOHAND ||
-                   res == -ERESTARTSYS ||
-                   res == -ERESTARTNOINTR) {
+               switch (res) {
+               case -ERESTARTNOHAND:
+               case -ERESTARTSYS:
+               case -ERESTARTNOINTR:
                        regs->rax = regs->orig_rax;
                        regs->rip -= 2;
-               }
-               if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK) {
+                       break;
+               case -ERESTART_RESTARTBLOCK:
                        regs->rax = test_thread_flag(TIF_IA32) ?
                                        __NR_ia32_restart_syscall :
                                        __NR_restart_syscall;
                        regs->rip -= 2;
+                       break;
                }
        }
-       return 0;
+
+       /* if there's no signal to deliver, we just put the saved sigmask
+          back. */
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
 }
 
-void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, __u32 thread_info_flags)
+void
+do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
 {
 #ifdef DEBUG_SIG
        printk("do_notify_resume flags:%x rip:%lx rsp:%lx caller:%lx pending:%lx\n",
@@ -491,8 +474,8 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, __u32 thread_info_
        }
 
        /* deal with pending signal delivery */
-       if (thread_info_flags & _TIF_SIGPENDING)
-               do_signal(regs,oldset);
+       if (thread_info_flags & (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK))
+               do_signal(regs);
 }
 
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
index 06af6ca601295e8253b95b999435710fdc8672e2..4f67697f5036faf1f37222ced236c0b3a04626c7 100644 (file)
@@ -522,26 +522,3 @@ asmlinkage void smp_call_function_interrupt(void)
        }
 }
 
-int safe_smp_processor_id(void)
-{
-       unsigned apicid, i;
-
-       if (disable_apic)
-               return 0;
-
-       apicid = hard_smp_processor_id();
-       if (apicid < NR_CPUS && x86_cpu_to_apicid[apicid] == apicid)
-               return apicid;
-
-       for (i = 0; i < NR_CPUS; ++i) {
-               if (x86_cpu_to_apicid[i] == apicid)
-                       return i;
-       }
-
-       /* No entries in x86_cpu_to_apicid?  Either no MPS|ACPI,
-        * or called too early.  Either way, we must be CPU 0. */
-       if (x86_cpu_to_apicid[0] == BAD_APICID)
-               return 0;
-
-       return 0; /* Should not happen */
-}
index 3ae9ffddddc0fa8de849aaf54c789bffba933dd6..7b7a6870288ac8dd2ae0188622d353949780c577 100644 (file)
@@ -1091,7 +1091,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        /*
         * Switch from PIC to APIC mode.
         */
-       connect_bsp_APIC();
        setup_local_APIC();
 
        if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_id) {
@@ -1176,12 +1175,9 @@ int __cpuinit __cpu_up(unsigned int cpu)
 void __init smp_cpus_done(unsigned int max_cpus)
 {
        smp_cleanup_boot();
-
-#ifdef CONFIG_X86_IO_APIC
        setup_ioapic_dest();
-#endif
-
        check_nmi_watchdog();
+       time_init_gtod();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -1234,6 +1230,8 @@ int __cpu_disable(void)
        if (cpu == 0)
                return -EBUSY;
 
+       if (nmi_watchdog == NMI_LOCAL_APIC)
+               stop_apic_nmi_watchdog(NULL);
        clear_local_APIC();
 
        /*
@@ -1273,11 +1271,11 @@ void __cpu_die(unsigned int cpu)
        printk(KERN_ERR "CPU %u didn't die...\n", cpu);
 }
 
-__init int setup_additional_cpus(char *s)
+static __init int setup_additional_cpus(char *s)
 {
-       return get_option(&s, &additional_cpus);
+       return s && get_option(&s, &additional_cpus) ? 0 : -EINVAL;
 }
-__setup("additional_cpus=", setup_additional_cpus);
+early_param("additional_cpus", setup_additional_cpus);
 
 #else /* ... !CONFIG_HOTPLUG_CPU */
 
index 32cf55eb9af87b33259afe4537504b958ebe6b53..6026b31d037ef72a9b92213f1b522b8ba8e8f0b0 100644 (file)
  */
 #include <linux/sched.h>
 #include <linux/stacktrace.h>
+#include <linux/module.h>
+#include <asm/stacktrace.h>
 
-#include <asm/smp.h>
-
-static inline int
-in_range(unsigned long start, unsigned long addr, unsigned long end)
+static void save_stack_warning(void *data, char *msg)
 {
-       return addr >= start && addr <= end;
 }
 
-static unsigned long
-get_stack_end(struct task_struct *task, unsigned long stack)
+static void
+save_stack_warning_symbol(void *data, char *msg, unsigned long symbol)
 {
-       unsigned long stack_start, stack_end, flags;
-       int i, cpu;
-
-       /*
-        * The most common case is that we are in the task stack:
-        */
-       stack_start = (unsigned long)task->thread_info;
-       stack_end = stack_start + THREAD_SIZE;
-
-       if (in_range(stack_start, stack, stack_end))
-               return stack_end;
-
-       /*
-        * We are in an interrupt if irqstackptr is set:
-        */
-       raw_local_irq_save(flags);
-       cpu = safe_smp_processor_id();
-       stack_end = (unsigned long)cpu_pda(cpu)->irqstackptr;
-
-       if (stack_end) {
-               stack_start = stack_end & ~(IRQSTACKSIZE-1);
-               if (in_range(stack_start, stack, stack_end))
-                       goto out_restore;
-               /*
-                * We get here if we are in an IRQ context but we
-                * are also in an exception stack.
-                */
-       }
-
-       /*
-        * Iterate over all exception stacks, and figure out whether
-        * 'stack' is in one of them:
-        */
-       for (i = 0; i < N_EXCEPTION_STACKS; i++) {
-               /*
-                * set 'end' to the end of the exception stack.
-                */
-               stack_end = per_cpu(init_tss, cpu).ist[i];
-               stack_start = stack_end - EXCEPTION_STKSZ;
-
-               /*
-                * Is 'stack' above this exception frame's end?
-                * If yes then skip to the next frame.
-                */
-               if (stack >= stack_end)
-                       continue;
-               /*
-                * Is 'stack' above this exception frame's start address?
-                * If yes then we found the right frame.
-                */
-               if (stack >= stack_start)
-                       goto out_restore;
-
-               /*
-                * If this is a debug stack, and if it has a larger size than
-                * the usual exception stacks, then 'stack' might still
-                * be within the lower portion of the debug stack:
-                */
-#if DEBUG_STKSZ > EXCEPTION_STKSZ
-               if (i == DEBUG_STACK - 1 && stack >= stack_end - DEBUG_STKSZ) {
-                       /*
-                        * Black magic. A large debug stack is composed of
-                        * multiple exception stack entries, which we
-                        * iterate through now. Dont look:
-                        */
-                       do {
-                               stack_end -= EXCEPTION_STKSZ;
-                               stack_start -= EXCEPTION_STKSZ;
-                       } while (stack < stack_start);
-
-                       goto out_restore;
-               }
-#endif
-       }
-       /*
-        * Ok, 'stack' is not pointing to any of the system stacks.
-        */
-       stack_end = 0;
-
-out_restore:
-       raw_local_irq_restore(flags);
-
-       return stack_end;
 }
 
-
-/*
- * Save stack-backtrace addresses into a stack_trace buffer:
- */
-static inline unsigned long
-save_context_stack(struct stack_trace *trace, unsigned int skip,
-                  unsigned long stack, unsigned long stack_end)
+static int save_stack_stack(void *data, char *name)
 {
-       unsigned long addr;
-
-#ifdef CONFIG_FRAME_POINTER
-       unsigned long prev_stack = 0;
+       struct stack_trace *trace = (struct stack_trace *)data;
+       return trace->all_contexts ? 0 : -1;
+}
 
-       while (in_range(prev_stack, stack, stack_end)) {
-               pr_debug("stack:          %p\n", (void *)stack);
-               addr = (unsigned long)(((unsigned long *)stack)[1]);
-               pr_debug("addr:           %p\n", (void *)addr);
-               if (!skip)
-                       trace->entries[trace->nr_entries++] = addr-1;
-               else
-                       skip--;
-               if (trace->nr_entries >= trace->max_entries)
-                       break;
-               if (!addr)
-                       return 0;
-               /*
-                * Stack frames must go forwards (otherwise a loop could
-                * happen if the stackframe is corrupted), so we move
-                * prev_stack forwards:
-                */
-               prev_stack = stack;
-               stack = (unsigned long)(((unsigned long *)stack)[0]);
-       }
-       pr_debug("invalid:        %p\n", (void *)stack);
-#else
-       while (stack < stack_end) {
-               addr = ((unsigned long *)stack)[0];
-               stack += sizeof(long);
-               if (__kernel_text_address(addr)) {
-                       if (!skip)
-                               trace->entries[trace->nr_entries++] = addr-1;
-                       else
-                               skip--;
-                       if (trace->nr_entries >= trace->max_entries)
-                               break;
-               }
+static void save_stack_address(void *data, unsigned long addr)
+{
+       struct stack_trace *trace = (struct stack_trace *)data;
+       if (trace->skip > 0) {
+               trace->skip--;
+               return;
        }
-#endif
-       return stack;
+       if (trace->nr_entries < trace->max_entries - 1)
+               trace->entries[trace->nr_entries++] = addr;
 }
 
-#define MAX_STACKS 10
+static struct stacktrace_ops save_stack_ops = {
+       .warning = save_stack_warning,
+       .warning_symbol = save_stack_warning_symbol,
+       .stack = save_stack_stack,
+       .address = save_stack_address,
+};
 
 /*
  * Save stack-backtrace addresses into a stack_trace buffer.
- * If all_contexts is set, all contexts (hardirq, softirq and process)
- * are saved. If not set then only the current context is saved.
  */
-void save_stack_trace(struct stack_trace *trace,
-                     struct task_struct *task, int all_contexts,
-                     unsigned int skip)
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
 {
-       unsigned long stack = (unsigned long)&stack;
-       int i, nr_stacks = 0, stacks_done[MAX_STACKS];
-
-       WARN_ON(trace->nr_entries || !trace->max_entries);
-
-       if (!task)
-               task = current;
-
-       pr_debug("task: %p, ti: %p\n", task, task->thread_info);
-
-       if (!task || task == current) {
-               /* Grab rbp right from our regs: */
-               asm ("mov %%rbp, %0" : "=r" (stack));
-               pr_debug("rbp:            %p\n", (void *)stack);
-       } else {
-               /* rbp is the last reg pushed by switch_to(): */
-               stack = task->thread.rsp;
-               pr_debug("other task rsp: %p\n", (void *)stack);
-               stack = (unsigned long)(((unsigned long *)stack)[0]);
-               pr_debug("other task rbp: %p\n", (void *)stack);
-       }
-
-       while (1) {
-               unsigned long stack_end = get_stack_end(task, stack);
-
-               pr_debug("stack:          %p\n", (void *)stack);
-               pr_debug("stack end:      %p\n", (void *)stack_end);
-
-               /*
-                * Invalid stack addres?
-                */
-               if (!stack_end)
-                       return;
-               /*
-                * Were we in this stack already? (recursion)
-                */
-               for (i = 0; i < nr_stacks; i++)
-                       if (stacks_done[i] == stack_end)
-                               return;
-               stacks_done[nr_stacks] = stack_end;
-
-               stack = save_context_stack(trace, skip, stack, stack_end);
-               if (!all_contexts || !stack ||
-                               trace->nr_entries >= trace->max_entries)
-                       return;
-               trace->entries[trace->nr_entries++] = ULONG_MAX;
-               if (trace->nr_entries >= trace->max_entries)
-                       return;
-               if (++nr_stacks >= MAX_STACKS)
-                       return;
-       }
+       dump_trace(task, NULL, NULL, &save_stack_ops, trace);
+       trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
+EXPORT_SYMBOL(save_stack_trace);
 
index 5530dda3f27ac3b84ec63a6e4f96662f4f50abc3..cbabfdf78e06982711daa1f1b03c161a66cc6455 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * This file manages the translation entries for the IBM Calgary IOMMU.
+ *
  * Derived from arch/powerpc/platforms/pseries/iommu.c
  *
  * Copyright (C) IBM Corporation, 2006
@@ -104,14 +106,6 @@ static int tce_table_setparms(struct pci_dev *dev, struct iommu_table *tbl)
        /* set the tce table size - measured in entries */
        tbl->it_size = table_size_to_number_of_entries(specified_table_size);
 
-       tbl->it_base = (unsigned long)tce_table_kva[dev->bus->number];
-       if (!tbl->it_base) {
-               printk(KERN_ERR "Calgary: iommu_table_setparms: "
-                      "no table allocated?!\n");
-               ret = -ENOMEM;
-               goto done;
-       }
-
        /*
         * number of bytes needed for the bitmap size in number of
         * entries; we need one bit per entry
@@ -160,8 +154,6 @@ int build_tce_table(struct pci_dev *dev, void __iomem *bbar)
        if (ret)
                goto free_tbl;
 
-       tce_free(tbl, 0, tbl->it_size);
-
        tbl->bbar = bbar;
 
        /*
index 7700e6cd2bd9567e63f26a3447f2a5092a5cbc5c..1c255ee76e7c81870768f54adc9a5fe149dc0239 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/device.h>
 #include <linux/sysdev.h>
 #include <linux/bcd.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
 #include <linux/kallsyms.h>
 #include <linux/acpi.h>
 #ifdef CONFIG_ACPI
@@ -39,9 +41,7 @@
 #include <asm/sections.h>
 #include <linux/cpufreq.h>
 #include <linux/hpet.h>
-#ifdef CONFIG_X86_LOCAL_APIC
 #include <asm/apic.h>
-#endif
 
 #ifdef CONFIG_CPU_FREQ
 static void cpufreq_delayed_get(void);
@@ -49,7 +49,7 @@ static void cpufreq_delayed_get(void);
 extern void i8254_timer_resume(void);
 extern int using_apic_timer;
 
-static char *time_init_gtod(void);
+static char *timename = NULL;
 
 DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
@@ -187,20 +187,15 @@ unsigned long profile_pc(struct pt_regs *regs)
 {
        unsigned long pc = instruction_pointer(regs);
 
-       /* Assume the lock function has either no stack frame or only a single 
-          word.  This checks if the address on the stack looks like a kernel 
-          text address.
-          There is a small window for false hits, but in that case the tick
-          is just accounted to the spinlock function.
-          Better would be to write these functions in assembler again
-          and check exactly. */
+       /* Assume the lock function has either no stack frame or a copy
+          of eflags from PUSHF
+          Eflags always has bits 22 and up cleared unlike kernel addresses. */
        if (!user_mode(regs) && in_lock_functions(pc)) {
-               char *v = *(char **)regs->rsp;
-               if ((v >= _stext && v <= _etext) ||
-                       (v >= _sinittext && v <= _einittext) ||
-                       (v >= (char *)MODULES_VADDR  && v <= (char *)MODULES_END))
-                       return (unsigned long)v;
-               return ((unsigned long *)regs->rsp)[1];
+               unsigned long *sp = (unsigned long *)regs->rsp;
+               if (sp[0] >> 22)
+                       return sp[0];
+               if (sp[1] >> 22)
+                       return sp[1];
        }
        return pc;
 }
@@ -281,6 +276,7 @@ static void set_rtc_mmss(unsigned long nowtime)
  *             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;
@@ -305,8 +301,7 @@ unsigned long long monotonic_clock(void)
                        base = monotonic_base;
                } while (read_seqretry(&xtime_lock, seq));
                this_offset = get_cycles_sync();
-               /* FIXME: 1000 or 1000000? */
-               offset = (this_offset - last_offset)*1000 / cpu_khz;
+               offset = cycles_2_ns(this_offset - last_offset);
        }
        return base + offset;
 }
@@ -410,8 +405,7 @@ void main_timer_handler(struct pt_regs *regs)
                        offset %= USEC_PER_TICK;
                }
 
-               /* FIXME: 1000 or 1000000? */
-               monotonic_base += (tsc - vxtime.last_tsc) * 1000000 / cpu_khz;
+               monotonic_base += cycles_2_ns(tsc - vxtime.last_tsc);
 
                vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot;
 
@@ -441,12 +435,8 @@ void main_timer_handler(struct pt_regs *regs)
  * have to call the local interrupt handler.
  */
 
-#ifndef CONFIG_X86_LOCAL_APIC
-       profile_tick(CPU_PROFILING, regs);
-#else
        if (!using_apic_timer)
                smp_local_timer_interrupt(regs);
-#endif
 
 /*
  * If we have an externally synchronized Linux clock, then update CMOS clock
@@ -470,10 +460,8 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        if (apic_runs_main_timer > 1)
                return IRQ_HANDLED;
        main_timer_handler(regs);
-#ifdef CONFIG_X86_LOCAL_APIC
        if (using_apic_timer)
                smp_send_timer_broadcast_ipi();
-#endif
        return IRQ_HANDLED;
 }
 
@@ -893,11 +881,17 @@ static struct irqaction irq0 = {
        timer_interrupt, IRQF_DISABLED, CPU_MASK_NONE, "timer", NULL, NULL
 };
 
-void __init time_init(void)
+static int __cpuinit
+time_cpu_notifier(struct notifier_block *nb, unsigned long action, void *hcpu)
 {
-       char *timename;
-       char *gtod;
+       unsigned cpu = (unsigned long) hcpu;
+       if (action == CPU_ONLINE)
+               vsyscall_set_cpu(cpu);
+       return NOTIFY_DONE;
+}
 
+void __init time_init(void)
+{
        if (nohpet)
                vxtime.hpet_address = 0;
 
@@ -931,18 +925,17 @@ void __init time_init(void)
        }
 
        vxtime.mode = VXTIME_TSC;
-       gtod = time_init_gtod();
-
-       printk(KERN_INFO "time.c: Using %ld.%06ld MHz WALL %s GTOD %s timer.\n",
-              vxtime_hz / 1000000, vxtime_hz % 1000000, timename, gtod);
-       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);
+       hotcpu_notifier(time_cpu_notifier, 0);
+       time_cpu_notifier(NULL, CPU_ONLINE, (void *)(long)smp_processor_id());
 
-       set_cyc2ns_scale(cpu_khz);
+#ifndef CONFIG_SMP
+       time_init_gtod();
+#endif
 }
 
 /*
@@ -973,12 +966,18 @@ __cpuinit int unsynchronized_tsc(void)
 /*
  * Decide what mode gettimeofday should use.
  */
-__init static char *time_init_gtod(void)
+void time_init_gtod(void)
 {
        char *timetype;
 
        if (unsynchronized_tsc())
                notsc = 1;
+
+       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)
@@ -1001,7 +1000,16 @@ __init static char *time_init_gtod(void)
                timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC";
                vxtime.mode = VXTIME_TSC;
        }
-       return timetype;
+
+       printk(KERN_INFO "time.c: Using %ld.%06ld MHz WALL %s GTOD %s timer.\n",
+              vxtime_hz / 1000000, vxtime_hz % 1000000, timename, timetype);
+       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("report_lost_ticks", time_setup);
@@ -1031,8 +1039,16 @@ static int timer_resume(struct sys_device *dev)
        unsigned long flags;
        unsigned long sec;
        unsigned long ctime = get_cmos_time();
-       unsigned long sleep_length = (ctime - sleep_start) * HZ;
+       long sleep_length = (ctime - sleep_start) * HZ;
 
+       if (sleep_length < 0) {
+               printk(KERN_WARNING "Time 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;
+       }
        if (vxtime.hpet_address)
                hpet_reenable();
        else
index 23a03eb91fc7ee7705dedec2a8fe1c5ecf013b5f..c79b99a9e2f68e78afc731ae86e6e0a17ebcee7d 100644 (file)
@@ -64,7 +64,7 @@ idt_48:
        .word   0, 0                    # idt base = 0L
 
 gdt_48:
-       .short  __KERNEL32_CS + 7       # gdt limit
+       .short  GDT_ENTRIES*8 - 1       # gdt limit
        .long   cpu_gdt_table-__START_KERNEL_map
 
 .globl trampoline_end
index b1249774d1e8af251f343357ddb6c627a0515751..01f2a8d254c2fd6683b423910b1af36a046add42 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/pda.h>
 #include <asm/proto.h>
 #include <asm/nmi.h>
+#include <asm/stacktrace.h>
 
 asmlinkage void divide_error(void);
 asmlinkage void debug(void);
@@ -142,7 +143,7 @@ void printk_address(unsigned long address)
 #endif
 
 static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
-                                       unsigned *usedp, const char **idp)
+                                       unsigned *usedp, char **idp)
 {
        static char ids[][8] = {
                [DEBUG_STACK - 1] = "#DB",
@@ -161,26 +162,7 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
         * 'stack' is in one of them:
         */
        for (k = 0; k < N_EXCEPTION_STACKS; k++) {
-               unsigned long end;
-
-               /*
-                * set 'end' to the end of the exception stack.
-                */
-               switch (k + 1) {
-               /*
-                * TODO: this block is not needed i think, because
-                * setup64.c:cpu_init() sets up t->ist[DEBUG_STACK]
-                * properly too.
-                */
-#if DEBUG_STKSZ > EXCEPTION_STKSZ
-               case DEBUG_STACK:
-                       end = cpu_pda(cpu)->debugstack + DEBUG_STKSZ;
-                       break;
-#endif
-               default:
-                       end = per_cpu(orig_ist, cpu).ist[k];
-                       break;
-               }
+               unsigned long end = per_cpu(orig_ist, cpu).ist[k];
                /*
                 * Is 'stack' above this exception frame's end?
                 * If yes then skip to the next frame.
@@ -234,13 +216,19 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
        return NULL;
 }
 
-static int show_trace_unwind(struct unwind_frame_info *info, void *context)
+struct ops_and_data {
+       struct stacktrace_ops *ops;
+       void *data;
+};
+
+static int dump_trace_unwind(struct unwind_frame_info *info, void *context)
 {
+       struct ops_and_data *oad = (struct ops_and_data *)context;
        int n = 0;
 
        while (unwind(info) == 0 && UNW_PC(info)) {
                n++;
-               printk_address(UNW_PC(info));
+               oad->ops->address(oad->data, UNW_PC(info));
                if (arch_unw_user_mode(info))
                        break;
        }
@@ -254,45 +242,53 @@ static int show_trace_unwind(struct unwind_frame_info *info, void *context)
  * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
  */
 
-void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack)
+void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * stack,
+               struct stacktrace_ops *ops, void *data)
 {
-       const unsigned cpu = safe_smp_processor_id();
+       const unsigned cpu = smp_processor_id();
        unsigned long *irqstack_end = (unsigned long *)cpu_pda(cpu)->irqstackptr;
        unsigned used = 0;
 
-       printk("\nCall Trace:\n");
-
        if (!tsk)
                tsk = current;
 
        if (call_trace >= 0) {
                int unw_ret = 0;
                struct unwind_frame_info info;
+               struct ops_and_data oad = { .ops = ops, .data = data };
 
                if (regs) {
                        if (unwind_init_frame_info(&info, tsk, regs) == 0)
-                               unw_ret = show_trace_unwind(&info, NULL);
+                               unw_ret = dump_trace_unwind(&info, &oad);
                } else if (tsk == current)
-                       unw_ret = unwind_init_running(&info, show_trace_unwind, NULL);
+                       unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad);
                else {
                        if (unwind_init_blocked(&info, tsk) == 0)
-                               unw_ret = show_trace_unwind(&info, NULL);
+                               unw_ret = dump_trace_unwind(&info, &oad);
                }
                if (unw_ret > 0) {
                        if (call_trace == 1 && !arch_unw_user_mode(&info)) {
-                               print_symbol("DWARF2 unwinder stuck at %s\n",
+                               ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n",
                                             UNW_PC(&info));
                                if ((long)UNW_SP(&info) < 0) {
-                                       printk("Leftover inexact backtrace:\n");
+                                       ops->warning(data, "Leftover inexact backtrace:\n");
                                        stack = (unsigned long *)UNW_SP(&info);
+                                       if (!stack)
+                                               return;
                                } else
-                                       printk("Full inexact backtrace again:\n");
+                                       ops->warning(data, "Full inexact backtrace again:\n");
                        } else if (call_trace >= 1)
                                return;
                        else
-                               printk("Full inexact backtrace again:\n");
+                               ops->warning(data, "Full inexact backtrace again:\n");
                } else
-                       printk("Inexact backtrace:\n");
+                       ops->warning(data, "Inexact backtrace:\n");
+       }
+       if (!stack) {
+               unsigned long dummy;
+               stack = &dummy;
+               if (tsk && tsk != current)
+                       stack = (unsigned long *)tsk->thread.rsp;
        }
 
        /*
@@ -303,7 +299,9 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
 #define HANDLE_STACK(cond) \
        do while (cond) { \
                unsigned long addr = *stack++; \
-               if (kernel_text_address(addr)) { \
+               if (oops_in_progress ?          \
+                       __kernel_text_address(addr) : \
+                       kernel_text_address(addr)) { \
                        /* \
                         * If the address is either in the text segment of the \
                         * kernel, or in the region which contains vmalloc'ed \
@@ -312,7 +310,7 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
                         * down the cause of the crash will be able to figure \
                         * out the call path that was taken. \
                         */ \
-                       printk_address(addr); \
+                       ops->address(data, addr);   \
                } \
        } while (0)
 
@@ -321,16 +319,17 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
         * current stack address. If the stacks consist of nested
         * exceptions
         */
-       for ( ; ; ) {
-               const char *id;
+       for (;;) {
+               char *id;
                unsigned long *estack_end;
                estack_end = in_exception_stack(cpu, (unsigned long)stack,
                                                &used, &id);
 
                if (estack_end) {
-                       printk(" <%s>", id);
+                       if (ops->stack(data, id) < 0)
+                               break;
                        HANDLE_STACK (stack < estack_end);
-                       printk(" <EOE>");
+                       ops->stack(data, "<EOE>");
                        /*
                         * We link to the next stack via the
                         * second-to-last pointer (index -2 to end) in the
@@ -345,7 +344,8 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
                                (IRQSTACKSIZE - 64) / sizeof(*irqstack);
 
                        if (stack >= irqstack && stack < irqstack_end) {
-                               printk(" <IRQ>");
+                               if (ops->stack(data, "IRQ") < 0)
+                                       break;
                                HANDLE_STACK (stack < irqstack_end);
                                /*
                                 * We link to the next stack (which would be
@@ -354,7 +354,7 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
                                 */
                                stack = (unsigned long *) (irqstack_end[-1]);
                                irqstack_end = NULL;
-                               printk(" <EOI>");
+                               ops->stack(data, "EOI");
                                continue;
                        }
                }
@@ -362,19 +362,57 @@ void show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long * s
        }
 
        /*
-        * This prints the process stack:
+        * This handles the process stack:
         */
        HANDLE_STACK (((long) stack & (THREAD_SIZE-1)) != 0);
 #undef HANDLE_STACK
+}
+EXPORT_SYMBOL(dump_trace);
+
+static void
+print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+       print_symbol(msg, symbol);
+       printk("\n");
+}
+
+static void print_trace_warning(void *data, char *msg)
+{
+       printk("%s\n", msg);
+}
+
+static int print_trace_stack(void *data, char *name)
+{
+       printk(" <%s> ", name);
+       return 0;
+}
+
+static void print_trace_address(void *data, unsigned long addr)
+{
+       printk_address(addr);
+}
+
+static struct stacktrace_ops print_trace_ops = {
+       .warning = print_trace_warning,
+       .warning_symbol = print_trace_warning_symbol,
+       .stack = print_trace_stack,
+       .address = print_trace_address,
+};
 
+void
+show_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack)
+{
+       printk("\nCall Trace:\n");
+       dump_trace(tsk, regs, stack, &print_trace_ops, NULL);
        printk("\n");
 }
 
-static void _show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long * rsp)
+static void
+_show_stack(struct task_struct *tsk, struct pt_regs *regs, unsigned long *rsp)
 {
        unsigned long *stack;
        int i;
-       const int cpu = safe_smp_processor_id();
+       const int cpu = smp_processor_id();
        unsigned long *irqstack_end = (unsigned long *) (cpu_pda(cpu)->irqstackptr);
        unsigned long *irqstack = (unsigned long *) (cpu_pda(cpu)->irqstackptr - IRQSTACKSIZE);
 
@@ -428,7 +466,7 @@ void show_registers(struct pt_regs *regs)
        int i;
        int in_kernel = !user_mode(regs);
        unsigned long rsp;
-       const int cpu = safe_smp_processor_id(); 
+       const int cpu = smp_processor_id();
        struct task_struct *cur = cpu_pda(cpu)->pcurrent;
 
                rsp = regs->rsp;
@@ -503,9 +541,11 @@ static unsigned int die_nest_count;
 
 unsigned __kprobes long oops_begin(void)
 {
-       int cpu = safe_smp_processor_id();
+       int cpu = smp_processor_id();
        unsigned long flags;
 
+       oops_enter();
+
        /* racy, but better than risking deadlock. */
        local_irq_save(flags);
        if (!spin_trylock(&die_lock)) { 
@@ -534,6 +574,7 @@ void __kprobes oops_end(unsigned long flags)
                spin_unlock_irqrestore(&die_lock, flags);
        if (panic_on_oops)
                panic("Fatal exception");
+       oops_exit();
 }
 
 void __kprobes __die(const char * str, struct pt_regs * regs, long err)
@@ -570,7 +611,7 @@ void die(const char * str, struct pt_regs * regs, long err)
        do_exit(SIGSEGV); 
 }
 
-void __kprobes die_nmi(char *str, struct pt_regs *regs)
+void __kprobes die_nmi(char *str, struct pt_regs *regs, int do_panic)
 {
        unsigned long flags = oops_begin();
 
@@ -578,13 +619,12 @@ void __kprobes die_nmi(char *str, struct pt_regs *regs)
         * We are in trouble anyway, lets at least try
         * to get a message out.
         */
-       printk(str, safe_smp_processor_id());
+       printk(str, smp_processor_id());
        show_registers(regs);
        if (kexec_should_crash(current))
                crash_kexec(regs);
-       if (panic_on_timeout || panic_on_oops)
-               panic("nmi watchdog");
-       printk("console shuts up ...\n");
+       if (do_panic || panic_on_oops)
+               panic("Non maskable interrupt");
        oops_end(flags);
        nmi_exit();
        local_irq_enable();
@@ -730,8 +770,15 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs,
 static __kprobes void
 mem_parity_error(unsigned char reason, struct pt_regs * regs)
 {
-       printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
-       printk("You probably have a hardware problem with your RAM chips\n");
+       printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+               reason);
+       printk(KERN_EMERG "You probably have a hardware problem with your "
+               "RAM chips\n");
+
+       if (panic_on_unrecovered_nmi)
+               panic("NMI: Not continuing");
+
+       printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
 
        /* Clear and disable the memory parity error line. */
        reason = (reason & 0xf) | 4;
@@ -754,9 +801,15 @@ io_check_error(unsigned char reason, struct pt_regs * regs)
 
 static __kprobes void
 unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
-{      printk("Uhhuh. NMI received for unknown reason %02x.\n", reason);
-       printk("Dazed and confused, but trying to continue\n");
-       printk("Do you have a strange power saving mode enabled?\n");
+{
+       printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x.\n",
+               reason);
+       printk(KERN_EMERG "Do you have a strange power saving mode enabled?\n");
+
+       if (panic_on_unrecovered_nmi)
+               panic("NMI: Not continuing");
+
+       printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
 }
 
 /* Runs on IST stack. This code must keep interrupts off all the time.
@@ -776,17 +829,15 @@ asmlinkage __kprobes void default_do_nmi(struct pt_regs *regs)
                if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 2, SIGINT)
                                                                == NOTIFY_STOP)
                        return;
-#ifdef CONFIG_X86_LOCAL_APIC
                /*
                 * Ok, so this is none of the documented NMI sources,
                 * so it must be the NMI watchdog.
                 */
-               if (nmi_watchdog > 0) {
-                       nmi_watchdog_tick(regs,reason);
+               if (nmi_watchdog_tick(regs,reason))
                        return;
-               }
-#endif
-               unknown_nmi_error(reason, regs);
+               if (!do_nmi_callback(regs,cpu))
+                       unknown_nmi_error(reason, regs);
+
                return;
        }
        if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_STOP)
@@ -1071,6 +1122,7 @@ asmlinkage void math_state_restore(void)
                init_fpu(me);
        restore_fpu_checking(&me->thread.i387.fxsave);
        task_thread_info(me)->status |= TS_USEDFPU;
+       me->fpu_counter++;
 }
 
 void __init trap_init(void)
@@ -1109,24 +1161,30 @@ void __init trap_init(void)
 }
 
 
-/* Actual parsing is done early in setup.c. */
-static int __init oops_dummy(char *s)
+static int __init oops_setup(char *s)
 { 
-       panic_on_oops = 1;
-       return 1;
+       if (!s)
+               return -EINVAL;
+       if (!strcmp(s, "panic"))
+               panic_on_oops = 1;
+       return 0;
 } 
-__setup("oops=", oops_dummy); 
+early_param("oops", oops_setup);
 
 static int __init kstack_setup(char *s)
 {
+       if (!s)
+               return -EINVAL;
        kstack_depth_to_print = simple_strtoul(s,NULL,0);
-       return 1;
+       return 0;
 }
-__setup("kstack=", kstack_setup);
+early_param("kstack", kstack_setup);
 
 #ifdef CONFIG_STACK_UNWIND
 static int __init call_trace_setup(char *s)
 {
+       if (!s)
+               return -EINVAL;
        if (strcmp(s, "old") == 0)
                call_trace = -1;
        else if (strcmp(s, "both") == 0)
@@ -1135,7 +1193,7 @@ static int __init call_trace_setup(char *s)
                call_trace = 1;
        else if (strcmp(s, "new") == 0)
                call_trace = 2;
-       return 1;
+       return 0;
 }
-__setup("call_trace=", call_trace_setup);
+early_param("call_trace", call_trace_setup);
 #endif
index 7c4de31471d40ab2bd09ac04b79b83cb9ad6bead..d0564f1bcb0b9aa62a42919bcbeb24f8c2725397 100644 (file)
@@ -13,6 +13,12 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
 OUTPUT_ARCH(i386:x86-64)
 ENTRY(phys_startup_64)
 jiffies_64 = jiffies;
+PHDRS {
+       text PT_LOAD FLAGS(5);  /* R_E */
+       data PT_LOAD FLAGS(7);  /* RWE */
+       user PT_LOAD FLAGS(7);  /* RWE */
+       note PT_NOTE FLAGS(4);  /* R__ */
+}
 SECTIONS
 {
   . = __START_KERNEL;
@@ -31,7 +37,7 @@ SECTIONS
        KPROBES_TEXT
        *(.fixup)
        *(.gnu.warning)
-       } = 0x9090
+       } :text = 0x9090
                                /* out-of-line lock text */
   .text.lock : AT(ADDR(.text.lock) - LOAD_OFFSET) { *(.text.lock) }
 
@@ -57,7 +63,7 @@ SECTIONS
   .data : AT(ADDR(.data) - LOAD_OFFSET) {
        *(.data)
        CONSTRUCTORS
-       }
+       } :data
 
   _edata = .;                  /* End of data section */
 
@@ -89,7 +95,7 @@ SECTIONS
 #define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
 
   . = VSYSCALL_ADDR;
-  .vsyscall_0 :         AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) }
+  .vsyscall_0 :         AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) } :user
   __vsyscall_0 = VSYSCALL_VIRT_ADDR;
 
   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
@@ -99,6 +105,9 @@ SECTIONS
   .vxtime : AT(VLOAD(.vxtime)) { *(.vxtime) }
   vxtime = VVIRT(.vxtime);
 
+  .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) }
+  vgetcpu_mode = VVIRT(.vgetcpu_mode);
+
   .wall_jiffies : AT(VLOAD(.wall_jiffies)) { *(.wall_jiffies) }
   wall_jiffies = VVIRT(.wall_jiffies);
 
@@ -132,7 +141,7 @@ SECTIONS
   . = ALIGN(8192);             /* init_task */
   .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
        *(.data.init_task)
-  }
+  } :data
 
   . = ALIGN(4096);
   .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
@@ -207,14 +216,12 @@ SECTIONS
   __initramfs_start = .;
   .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
   __initramfs_end = .;
-  /* temporary here to work around NR_CPUS. If you see this comment in 2.6.17+
-   complain */
-  . = ALIGN(4096);     
-  __init_end = .;      
-  . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+    . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
   __per_cpu_start = .;
   .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
   __per_cpu_end = .;
+  . = ALIGN(4096);
+  __init_end = .;
 
   . = ALIGN(4096);
   __nosave_begin = .;
index 92f70c74965f8cbb29e44bf9e36e41b3b9b6dc89..044e852bd25efb297c10545211d5fe80d5dfbf22 100644 (file)
@@ -20,6 +20,9 @@ static int __init vsmp_init(void)
        void *address;
        unsigned int cap, ctl;
 
+       if (!early_pci_allowed())
+               return 0;
+
        /* Check if we are running on a ScaleMP vSMP box */
        if ((read_pci_config_16(0, 0x1f, 0, PCI_VENDOR_ID) != PCI_VENDOR_ID_SCALEMP) ||
            (read_pci_config_16(0, 0x1f, 0, PCI_DEVICE_ID) != PCI_DEVICE_ID_SCALEMP_VSMP_CTL))
index f603037df1621d9d4d8ed1689c18488c19a047ca..ac48c3857ddb2164b34f857e6fe659b5b154b9b3 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/seqlock.h>
 #include <linux/jiffies.h>
 #include <linux/sysctl.h>
+#include <linux/getcpu.h>
 
 #include <asm/vsyscall.h>
 #include <asm/pgtable.h>
 #include <asm/fixmap.h>
 #include <asm/errno.h>
 #include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/desc.h>
+#include <asm/topology.h>
 
 #define __vsyscall(nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))
 
 int __sysctl_vsyscall __section_sysctl_vsyscall = 1;
 seqlock_t __xtime_lock __section_xtime_lock = SEQLOCK_UNLOCKED;
+int __vgetcpu_mode __section_vgetcpu_mode;
 
 #include <asm/unistd.h>
 
@@ -72,7 +77,8 @@ static __always_inline void do_vgettimeofday(struct timeval * tv)
                                 __vxtime.tsc_quot) >> 32;
                        /* See comment in x86_64 do_gettimeofday. */
                } else {
-                       usec += ((readl((void *)fix_to_virt(VSYSCALL_HPET) + 0xf0) -
+                       usec += ((readl((void __iomem *)
+                                  fix_to_virt(VSYSCALL_HPET) + 0xf0) -
                                  __vxtime.last) * __vxtime.quot) >> 32;
                }
        } while (read_seqretry(&__xtime_lock, sequence));
@@ -127,9 +133,46 @@ time_t __vsyscall(1) vtime(time_t *t)
        return __xtime.tv_sec;
 }
 
-long __vsyscall(2) venosys_0(void)
+/* Fast way to get current CPU and node.
+   This helps to do per node and per CPU caches in user space.
+   The result is not guaranteed without CPU affinity, but usually
+   works out because the scheduler tries to keep a thread on the same
+   CPU.
+
+   tcache must point to a two element sized long array.
+   All arguments can be NULL. */
+long __vsyscall(2)
+vgetcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache)
 {
-       return -ENOSYS;
+       unsigned int dummy, p;
+       unsigned long j = 0;
+
+       /* Fast cache - only recompute value once per jiffies and avoid
+          relatively costly rdtscp/cpuid otherwise.
+          This works because the scheduler usually keeps the process
+          on the same CPU and this syscall doesn't guarantee its
+          results anyways.
+          We do this here because otherwise user space would do it on
+          its own in a likely inferior way (no access to jiffies).
+          If you don't like it pass NULL. */
+       if (tcache && tcache->t0 == (j = __jiffies)) {
+               p = tcache->t1;
+       } else if (__vgetcpu_mode == VGETCPU_RDTSCP) {
+               /* Load per CPU data from RDTSCP */
+               rdtscp(dummy, dummy, p);
+       } else {
+               /* Load per CPU data from GDT */
+               asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG));
+       }
+       if (tcache) {
+               tcache->t0 = j;
+               tcache->t1 = p;
+       }
+       if (cpu)
+               *cpu = p & 0xfff;
+       if (node)
+               *node = p >> 12;
+       return 0;
 }
 
 long __vsyscall(3) venosys_1(void)
@@ -149,7 +192,8 @@ static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
                         void __user *buffer, size_t *lenp, loff_t *ppos)
 {
        extern u16 vsysc1, vsysc2;
-       u16 *map1, *map2;
+       u16 __iomem *map1;
+       u16 __iomem *map2;
        int ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
        if (!write)
                return ret;
@@ -164,11 +208,11 @@ static int vsyscall_sysctl_change(ctl_table *ctl, int write, struct file * filp,
                goto out;
        }
        if (!sysctl_vsyscall) {
-               *map1 = SYSCALL;
-               *map2 = SYSCALL;
+               writew(SYSCALL, map1);
+               writew(SYSCALL, map2);
        } else {
-               *map1 = NOP2;
-               *map2 = NOP2;
+               writew(NOP2, map1);
+               writew(NOP2, map2);
        }
        iounmap(map2);
 out:
@@ -200,6 +244,43 @@ static ctl_table kernel_root_table2[] = {
 
 #endif
 
+static void __cpuinit write_rdtscp_cb(void *info)
+{
+       write_rdtscp_aux((unsigned long)info);
+}
+
+void __cpuinit vsyscall_set_cpu(int cpu)
+{
+       unsigned long *d;
+       unsigned long node = 0;
+#ifdef CONFIG_NUMA
+       node = cpu_to_node[cpu];
+#endif
+       if (cpu_has(&cpu_data[cpu], X86_FEATURE_RDTSCP)) {
+               void *info = (void *)((node << 12) | cpu);
+               /* Can happen on preemptive kernel */
+               if (get_cpu() == cpu)
+                       write_rdtscp_cb(info);
+#ifdef CONFIG_SMP
+               else {
+                       /* the notifier is unfortunately not executed on the
+                          target CPU */
+                       smp_call_function_single(cpu,write_rdtscp_cb,info,0,1);
+               }
+#endif
+               put_cpu();
+       }
+
+       /* Store cpu number in limit so that it can be loaded quickly
+          in user space in vgetcpu.
+          12 bits for the CPU and 8 bits for the node. */
+       d = (unsigned long *)(cpu_gdt(cpu) + GDT_ENTRY_PER_CPU);
+       *d = 0x0f40000000000ULL;
+       *d |= cpu;
+       *d |= (node & 0xf) << 12;
+       *d |= (node >> 4) << 48;
+}
+
 static void __init map_vsyscall(void)
 {
        extern char __vsyscall_0;
@@ -214,6 +295,7 @@ static int __init vsyscall_init(void)
                        VSYSCALL_ADDR(__NR_vgettimeofday)));
        BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
        BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
+       BUG_ON((unsigned long) &vgetcpu != VSYSCALL_ADDR(__NR_vgetcpu));
        map_vsyscall();
 #ifdef CONFIG_SYSCTL
        register_sysctl_table(kernel_root_table2, 0);
index 370952c4ff228b79dd5663c1df3de7d56737747a..c3454af5e3a25896ca6cac599c0e21ce10e73a26 100644 (file)
@@ -29,6 +29,7 @@ EXPORT_SYMBOL(__put_user_8);
 EXPORT_SYMBOL(copy_user_generic);
 EXPORT_SYMBOL(copy_from_user);
 EXPORT_SYMBOL(copy_to_user);
+EXPORT_SYMBOL(__copy_from_user_inatomic);
 
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(clear_page);
index ccef6ae747a3bd395ae2a0294fec8306604c29bd..b78d4170fce230ea2d1797295a9248d1efdc66ea 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
+lib-y += memcpy.o memmove.o memset.o copy_user.o rwlock.o
index 1f81b79b796cc04e47ef0f22b98a79174b51279c..9a10a78bb4a414867fa68099996c6cfb66f26d2e 100644 (file)
@@ -1,10 +1,22 @@
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
 /*
  * Zero a page.        
  * rdi page
  */                    
-       .globl clear_page
-       .p2align 4
-clear_page:
+       ALIGN
+clear_page_c:
+       CFI_STARTPROC
+       movl $4096/8,%ecx
+       xorl %eax,%eax
+       rep stosq
+       ret
+       CFI_ENDPROC
+ENDPROC(clear_page)
+
+ENTRY(clear_page)
+       CFI_STARTPROC
        xorl   %eax,%eax
        movl   $4096/64,%ecx
        .p2align 4
@@ -23,28 +35,25 @@ clear_page:
        jnz     .Lloop
        nop
        ret
-clear_page_end:
+       CFI_ENDPROC
+.Lclear_page_end:
+ENDPROC(clear_page)
 
        /* Some CPUs run faster using the string instructions.
           It is also a lot simpler. Use this when possible */
 
 #include <asm/cpufeature.h>
 
+       .section .altinstr_replacement,"ax"
+1:     .byte 0xeb                                      /* jmp <disp8> */
+       .byte (clear_page_c - clear_page) - (2f - 1b)   /* offset */
+2:
+       .previous
        .section .altinstructions,"a"
        .align 8
-       .quad  clear_page
-       .quad  clear_page_c
-       .byte  X86_FEATURE_REP_GOOD
-       .byte  clear_page_end-clear_page
-       .byte  clear_page_c_end-clear_page_c
-       .previous
-
-       .section .altinstr_replacement,"ax"
-clear_page_c:
-       movl $4096/8,%ecx
-       xorl %eax,%eax
-       rep 
-       stosq
-       ret
-clear_page_c_end:
+       .quad clear_page
+       .quad 1b
+       .byte X86_FEATURE_REP_GOOD
+       .byte .Lclear_page_end - clear_page
+       .byte 2b - 1b
        .previous
index 8fa19d96a7eefde6b7d591fba46705486055818f..0ebb03b60e797946ff5aae6952b7e94fae5d5d25 100644 (file)
@@ -1,17 +1,33 @@
 /* Written 2003 by Andi Kleen, based on a kernel by Evandro Menezes */
        
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
+       ALIGN
+copy_page_c:
+       CFI_STARTPROC
+       movl $4096/8,%ecx
+       rep movsq
+       ret
+       CFI_ENDPROC
+ENDPROC(copy_page_c)
+
 /* Don't use streaming store because it's better when the target
    ends up in cache. */
            
 /* Could vary the prefetch distance based on SMP/UP */
 
-       .globl copy_page
-       .p2align 4
-copy_page:
+ENTRY(copy_page)
+       CFI_STARTPROC
        subq    $3*8,%rsp
+       CFI_ADJUST_CFA_OFFSET 3*8
        movq    %rbx,(%rsp)
+       CFI_REL_OFFSET rbx, 0
        movq    %r12,1*8(%rsp)
+       CFI_REL_OFFSET r12, 1*8
        movq    %r13,2*8(%rsp)
+       CFI_REL_OFFSET r13, 2*8
 
        movl    $(4096/64)-5,%ecx
        .p2align 4
@@ -72,30 +88,33 @@ copy_page:
        jnz     .Loop2
 
        movq    (%rsp),%rbx
+       CFI_RESTORE rbx
        movq    1*8(%rsp),%r12
+       CFI_RESTORE r12
        movq    2*8(%rsp),%r13
+       CFI_RESTORE r13
        addq    $3*8,%rsp
+       CFI_ADJUST_CFA_OFFSET -3*8
        ret
+.Lcopy_page_end:
+       CFI_ENDPROC
+ENDPROC(copy_page)
 
        /* Some CPUs run faster using the string copy instructions.
           It is also a lot simpler. Use this when possible */
 
 #include <asm/cpufeature.h>
 
+       .section .altinstr_replacement,"ax"
+1:     .byte 0xeb                                      /* jmp <disp8> */
+       .byte (copy_page_c - copy_page) - (2f - 1b)     /* offset */
+2:
+       .previous
        .section .altinstructions,"a"
        .align 8
-       .quad  copy_page
-       .quad  copy_page_c
-       .byte  X86_FEATURE_REP_GOOD
-       .byte  copy_page_c_end-copy_page_c
-       .byte  copy_page_c_end-copy_page_c
-       .previous
-
-       .section .altinstr_replacement,"ax"
-copy_page_c:
-       movl $4096/8,%ecx
-       rep 
-       movsq 
-       ret
-copy_page_c_end:
+       .quad copy_page
+       .quad 1b
+       .byte X86_FEATURE_REP_GOOD
+       .byte .Lcopy_page_end - copy_page
+       .byte 2b - 1b
        .previous
index f64569b83b548605c51d9ff6d31f4542eb9b59f9..70bebd310408b98b531a721f7d83ca4ee97d0369 100644 (file)
@@ -4,56 +4,78 @@
  * 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>
+#include <asm/current.h>
+#include <asm/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/cpufeature.h>
 
-/* Standard copy_to_user with segment limit checking */                
-       .globl copy_to_user
-       .p2align 4      
-copy_to_user:
-       GET_THREAD_INFO(%rax)
-       movq %rdi,%rcx
-       addq %rdx,%rcx
-       jc  bad_to_user
-       cmpq threadinfo_addr_limit(%rax),%rcx
-       jae bad_to_user
-2:
+       .macro ALTERNATIVE_JUMP feature,orig,alt
+0:
        .byte 0xe9      /* 32bit jump */
-       .long .Lcug-1f
+       .long \orig-1f  /* by default jump to orig */
 1:
-
        .section .altinstr_replacement,"ax"
-3:     .byte 0xe9                      /* replacement jmp with 8 bit immediate */
-       .long copy_user_generic_c-1b    /* offset */
+2:     .byte 0xe9                   /* near jump with 32bit immediate */
+       .long \alt-1b /* offset */   /* or alternatively to alt */
        .previous
        .section .altinstructions,"a"
        .align 8
+       .quad  0b
        .quad  2b
-       .quad  3b
-       .byte  X86_FEATURE_REP_GOOD
+       .byte  \feature              /* when feature is set */
        .byte  5
        .byte  5
        .previous
+       .endm
+
+/* Standard copy_to_user with segment limit checking */                
+ENTRY(copy_to_user)
+       CFI_STARTPROC
+       GET_THREAD_INFO(%rax)
+       movq %rdi,%rcx
+       addq %rdx,%rcx
+       jc  bad_to_user
+       cmpq threadinfo_addr_limit(%rax),%rcx
+       jae bad_to_user
+       xorl %eax,%eax  /* clear zero flag */
+       ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+       CFI_ENDPROC
+
+ENTRY(copy_user_generic)
+       CFI_STARTPROC
+       movl $1,%ecx    /* set zero flag */
+       ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+       CFI_ENDPROC
+
+ENTRY(__copy_from_user_inatomic)
+       CFI_STARTPROC
+       xorl %ecx,%ecx  /* clear zero flag */
+       ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+       CFI_ENDPROC
 
 /* Standard copy_from_user with segment limit checking */      
-       .globl copy_from_user
-       .p2align 4      
-copy_from_user:
+ENTRY(copy_from_user)
+       CFI_STARTPROC
        GET_THREAD_INFO(%rax)
        movq %rsi,%rcx
        addq %rdx,%rcx
        jc  bad_from_user
        cmpq threadinfo_addr_limit(%rax),%rcx
        jae  bad_from_user
-       /* FALL THROUGH to copy_user_generic */
+       movl $1,%ecx    /* set zero flag */
+       ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+       CFI_ENDPROC
+ENDPROC(copy_from_user)
        
        .section .fixup,"ax"
        /* must zero dest */
 bad_from_user:
+       CFI_STARTPROC
        movl %edx,%ecx
        xorl %eax,%eax
        rep
@@ -61,40 +83,32 @@ bad_from_user:
 bad_to_user:
        movl    %edx,%eax
        ret
+       CFI_ENDPROC
+END(bad_from_user)
        .previous
        
                
 /*
- * copy_user_generic - memory copy with exception handling.
+ * copy_user_generic_unrolled - memory copy with exception handling.
+ * This version is for CPUs like P4 that don't have efficient micro code for rep movsq
  *     
  * Input:      
  * rdi destination
  * rsi source
  * rdx count
+ * ecx zero flag -- if true zero destination on error
  *
  * Output:             
  * eax uncopied bytes or 0 if successful.
  */
-       .globl copy_user_generic
-       .p2align 4
-copy_user_generic:
-       .byte 0x66,0x66,0x90    /* 5 byte nop for replacement jump */
-       .byte 0x66,0x90
-1:
-       .section .altinstr_replacement,"ax"
-2:     .byte 0xe9                   /* near jump with 32bit immediate */
-       .long copy_user_generic_c-1b /* offset */
-       .previous
-       .section .altinstructions,"a"
-       .align 8
-       .quad  copy_user_generic
-       .quad  2b
-       .byte  X86_FEATURE_REP_GOOD
-       .byte  5
-       .byte  5
-       .previous
-.Lcug:
+ENTRY(copy_user_generic_unrolled)
+       CFI_STARTPROC
        pushq %rbx
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rbx, 0
+       pushq %rcx
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rcx, 0
        xorl %eax,%eax          /*zero for the exception handler */
 
 #ifdef FIX_ALIGNMENT
@@ -168,9 +182,16 @@ copy_user_generic:
        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 */
@@ -252,6 +273,8 @@ copy_user_generic:
        addl %ecx,%edx
        /* edx: bytes to zero, rdi: dest, eax:zero */
 .Lzero_rest:
+       cmpl $0,(%rsp)
+       jz   .Le_zero
        movq %rdx,%rcx
 .Le_byte:
        xorl %eax,%eax
@@ -261,6 +284,9 @@ copy_user_generic:
 .Le_zero:
        movq %rdx,%rax
        jmp .Lende
+       CFI_ENDPROC
+ENDPROC(copy_user_generic)
+
 
        /* Some CPUs run faster using the string copy instructions.
           This is also a lot simpler. Use them when possible.
@@ -270,6 +296,7 @@ copy_user_generic:
  /* rdi        destination
   * rsi source
   * rdx count
+  * ecx zero flag
   *
   * Output:
   * eax uncopied bytes or 0 if successfull.
@@ -280,22 +307,48 @@ copy_user_generic:
   * And more would be dangerous because both Intel and AMD have
   * errata with rep movsq > 4GB. If someone feels the need to fix
   * this please consider this.
-   */
-copy_user_generic_c:
+  */
+ENTRY(copy_user_generic_string)
+       CFI_STARTPROC
+       movl %ecx,%r8d          /* save zero flag */
        movl %edx,%ecx
        shrl $3,%ecx
        andl $7,%edx    
+       jz   10f
 1:     rep 
        movsq 
        movl %edx,%ecx
 2:     rep
        movsb
-4:     movl %ecx,%eax
+9:     movl %ecx,%eax
        ret
-3:     lea (%rdx,%rcx,8),%rax
+
+       /* multiple of 8 byte */
+10:    rep
+       movsq
+       xor %eax,%eax
        ret
 
+       /* exception handling */
+3:      lea (%rdx,%rcx,8),%rax /* exception on quad loop */
+       jmp 6f
+5:     movl %ecx,%eax          /* exception on byte loop */
+       /* eax: left over bytes */
+6:     testl %r8d,%r8d         /* zero flag set? */
+       jz 7f
+       movl %eax,%ecx          /* initialize x86 loop counter */
+       push %rax
+       xorl %eax,%eax
+8:     rep
+       stosb                   /* zero the rest */
+11:    pop %rax
+7:     ret
+       CFI_ENDPROC
+END(copy_user_generic_c)
+
        .section __ex_table,"a"
        .quad 1b,3b
-       .quad 2b,4b
+       .quad 2b,5b
+       .quad 8b,11b
+       .quad 10b,3b
        .previous
index 72fd55ee896ee1c4bd7064dc588573c7926e63d8..f0dba36578ea0765827efc68f9448dd38f12e6f0 100644 (file)
@@ -5,8 +5,9 @@
  * License.  See the file COPYING in the main directory of this archive
  * for more details. No warranty for anything given at all.
  */
-       #include <linux/linkage.h>
-       #include <asm/errno.h>
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+#include <asm/errno.h>
 
 /*
  * Checksum copy with exception handling.
        .endm
        
                                
-       .globl csum_partial_copy_generic
-       .p2align 4
-csum_partial_copy_generic:
+ENTRY(csum_partial_copy_generic)
+       CFI_STARTPROC
        cmpl     $3*64,%edx
        jle      .Lignore
 
 .Lignore:              
        subq  $7*8,%rsp
+       CFI_ADJUST_CFA_OFFSET 7*8
        movq  %rbx,2*8(%rsp)
+       CFI_REL_OFFSET rbx, 2*8
        movq  %r12,3*8(%rsp)
+       CFI_REL_OFFSET r12, 3*8
        movq  %r14,4*8(%rsp)
+       CFI_REL_OFFSET r14, 4*8
        movq  %r13,5*8(%rsp)
+       CFI_REL_OFFSET r13, 5*8
        movq  %rbp,6*8(%rsp)
+       CFI_REL_OFFSET rbp, 6*8
 
        movq  %r8,(%rsp)
        movq  %r9,1*8(%rsp)
@@ -208,14 +214,22 @@ csum_partial_copy_generic:
        addl %ebx,%eax
        adcl %r9d,%eax          /* carry */
                        
+       CFI_REMEMBER_STATE
 .Lende:
        movq 2*8(%rsp),%rbx
+       CFI_RESTORE rbx
        movq 3*8(%rsp),%r12
+       CFI_RESTORE r12
        movq 4*8(%rsp),%r14
+       CFI_RESTORE r14
        movq 5*8(%rsp),%r13
+       CFI_RESTORE r13
        movq 6*8(%rsp),%rbp
+       CFI_RESTORE rbp
        addq $7*8,%rsp
+       CFI_ADJUST_CFA_OFFSET -7*8
        ret
+       CFI_RESTORE_STATE
 
        /* Exception handlers. Very simple, zeroing is done in the wrappers */
 .Lbad_source:
@@ -231,3 +245,5 @@ csum_partial_copy_generic:
        jz   .Lende     
        movl $-EFAULT,(%rax)
        jmp .Lende
+       CFI_ENDPROC
+ENDPROC(csum_partial_copy_generic)
index 3844d5e885a4deafcc035334e7d86b48351daf52..5448876261f8734b2b4367c3295dd074c8d33542 100644 (file)
  */
 
 #include <linux/linkage.h>
+#include <asm/dwarf2.h>
 #include <asm/page.h>
 #include <asm/errno.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 
        .text
-       .p2align 4
-.globl __get_user_1
-__get_user_1:  
+ENTRY(__get_user_1)
+       CFI_STARTPROC
        GET_THREAD_INFO(%r8)
        cmpq threadinfo_addr_limit(%r8),%rcx
        jae bad_get_user
 1:     movzb (%rcx),%edx
        xorl %eax,%eax
        ret
+       CFI_ENDPROC
+ENDPROC(__get_user_1)
 
-       .p2align 4
-.globl __get_user_2
-__get_user_2:
+ENTRY(__get_user_2)
+       CFI_STARTPROC
        GET_THREAD_INFO(%r8)
        addq $1,%rcx
        jc 20f
@@ -57,10 +58,11 @@ __get_user_2:
        ret
 20:    decq    %rcx
        jmp     bad_get_user
+       CFI_ENDPROC
+ENDPROC(__get_user_2)
 
-       .p2align 4
-.globl __get_user_4
-__get_user_4:
+ENTRY(__get_user_4)
+       CFI_STARTPROC
        GET_THREAD_INFO(%r8)
        addq $3,%rcx
        jc 30f
@@ -72,10 +74,11 @@ __get_user_4:
        ret
 30:    subq $3,%rcx
        jmp bad_get_user
+       CFI_ENDPROC
+ENDPROC(__get_user_4)
 
-       .p2align 4
-.globl __get_user_8
-__get_user_8:
+ENTRY(__get_user_8)
+       CFI_STARTPROC
        GET_THREAD_INFO(%r8)
        addq $7,%rcx
        jc 40f
@@ -87,11 +90,16 @@ __get_user_8:
        ret
 40:    subq $7,%rcx
        jmp bad_get_user
+       CFI_ENDPROC
+ENDPROC(__get_user_8)
 
 bad_get_user:
+       CFI_STARTPROC
        xorl %edx,%edx
        movq $(-EFAULT),%rax
        ret
+       CFI_ENDPROC
+END(bad_get_user)
 
 .section __ex_table,"a"
        .quad 1b,bad_get_user
index 8bbade5fea056950a7b9710b5d2eb86a483f28c5..05a95e713da885e8686bc2bba1fdf544c03d2d74 100644 (file)
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
 /*
  * override generic version in lib/iomap_copy.c
  */
-       .globl __iowrite32_copy
-       .p2align 4
-__iowrite32_copy:
+ENTRY(__iowrite32_copy)
+       CFI_STARTPROC
        movl %edx,%ecx
        rep movsd
        ret
+       CFI_ENDPROC
+ENDPROC(__iowrite32_copy)
index 5554948b55549e2c7837264ce9bcae6b552e5a94..967b22fa7d07d59d21985eebdbb56298b81b8db4 100644 (file)
@@ -1,6 +1,10 @@
 /* Copyright 2002 Andi Kleen */
        
-       #include <asm/cpufeature.h>             
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+#include <asm/cpufeature.h>
+
 /*
  * memcpy - Copy a memory block.
  *
  * rax original destination
  */    
 
-       .globl __memcpy
-       .globl memcpy
-       .p2align 4
-__memcpy:
-memcpy:                
+       ALIGN
+memcpy_c:
+       CFI_STARTPROC
+       movq %rdi,%rax
+       movl %edx,%ecx
+       shrl $3,%ecx
+       andl $7,%edx
+       rep movsq
+       movl %edx,%ecx
+       rep movsb
+       ret
+       CFI_ENDPROC
+ENDPROC(memcpy_c)
+
+ENTRY(__memcpy)
+ENTRY(memcpy)
+       CFI_STARTPROC
        pushq %rbx
+       CFI_ADJUST_CFA_OFFSET 8
+       CFI_REL_OFFSET rbx, 0
        movq %rdi,%rax
 
        movl %edx,%ecx
@@ -86,36 +104,27 @@ memcpy:
 
 .Lende:
        popq %rbx
+       CFI_ADJUST_CFA_OFFSET -8
+       CFI_RESTORE rbx
        ret
 .Lfinal:
+       CFI_ENDPROC
+ENDPROC(memcpy)
+ENDPROC(__memcpy)
 
        /* Some CPUs run faster using the string copy instructions.
           It is also a lot simpler. Use this when possible */
 
+       .section .altinstr_replacement,"ax"
+1:     .byte 0xeb                              /* jmp <disp8> */
+       .byte (memcpy_c - memcpy) - (2f - 1b)   /* offset */
+2:
+       .previous
        .section .altinstructions,"a"
        .align 8
-       .quad  memcpy
-       .quad  memcpy_c
-       .byte  X86_FEATURE_REP_GOOD
-       .byte  .Lfinal-memcpy
-       .byte  memcpy_c_end-memcpy_c
-       .previous
-
-       .section .altinstr_replacement,"ax"
- /* rdi        destination
-  * rsi source
-  * rdx count
-  */
-memcpy_c:
-       movq %rdi,%rax
-       movl %edx,%ecx
-       shrl $3,%ecx
-       andl $7,%edx    
-       rep 
-       movsq 
-       movl %edx,%ecx
-       rep
-       movsb
-       ret
-memcpy_c_end:
+       .quad memcpy
+       .quad 1b
+       .byte X86_FEATURE_REP_GOOD
+       .byte .Lfinal - memcpy
+       .byte 2b - 1b
        .previous
index ad397f2c7de8fa7c73185793ba973bdfaed39b0b..09ed1f6b0eaa2c9037abb072db6bd4684d8bb6c2 100644 (file)
@@ -1,4 +1,9 @@
 /* Copyright 2002 Andi Kleen, SuSE Labs */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
 /*
  * ISO C memset - set a memory block to a byte value.
  *     
  * 
  * rax   original destination
  */    
-       .globl __memset
-       .globl memset
-       .p2align 4
-memset:        
-__memset:
+       ALIGN
+memset_c:
+       CFI_STARTPROC
+       movq %rdi,%r9
+       movl %edx,%r8d
+       andl $7,%r8d
+       movl %edx,%ecx
+       shrl $3,%ecx
+       /* expand byte value  */
+       movzbl %sil,%esi
+       movabs $0x0101010101010101,%rax
+       mulq %rsi               /* with rax, clobbers rdx */
+       rep stosq
+       movl %r8d,%ecx
+       rep stosb
+       movq %r9,%rax
+       ret
+       CFI_ENDPROC
+ENDPROC(memset_c)
+
+ENTRY(memset)
+ENTRY(__memset)
+       CFI_STARTPROC
        movq %rdi,%r10
        movq %rdx,%r11
 
@@ -25,6 +48,7 @@ __memset:
        movl  %edi,%r9d
        andl  $7,%r9d
        jnz  .Lbad_alignment
+       CFI_REMEMBER_STATE
 .Lafter_bad_alignment:
 
        movl %r11d,%ecx
@@ -75,6 +99,7 @@ __memset:
        movq    %r10,%rax
        ret
 
+       CFI_RESTORE_STATE
 .Lbad_alignment:
        cmpq $7,%r11
        jbe     .Lhandle_7
@@ -84,42 +109,26 @@ __memset:
        addq %r8,%rdi
        subq %r8,%r11
        jmp .Lafter_bad_alignment
+.Lfinal:
+       CFI_ENDPROC
+ENDPROC(memset)
+ENDPROC(__memset)
 
        /* Some CPUs run faster using the string instructions.
           It is also a lot simpler. Use this when possible */
 
 #include <asm/cpufeature.h>
 
+       .section .altinstr_replacement,"ax"
+1:     .byte 0xeb                              /* jmp <disp8> */
+       .byte (memset_c - memset) - (2f - 1b)   /* offset */
+2:
+       .previous
        .section .altinstructions,"a"
        .align 8
-       .quad  memset
-       .quad  memset_c
-       .byte  X86_FEATURE_REP_GOOD
-       .byte  memset_c_end-memset_c
-       .byte  memset_c_end-memset_c
-       .previous
-
-       .section .altinstr_replacement,"ax"
- /* rdi        destination
-  * rsi value
-  * rdx count
-  */
-memset_c:
-       movq %rdi,%r9
-       movl %edx,%r8d
-       andl $7,%r8d            
-       movl %edx,%ecx
-       shrl $3,%ecx            
-       /* expand byte value  */
-       movzbl %sil,%esi
-       movabs $0x0101010101010101,%rax
-       mulq   %rsi             /* with rax, clobbers rdx */
-       rep
-       stosq   
-       movl %r8d,%ecx
-       rep
-       stosb
-       movq %r9,%rax
-       ret
-memset_c_end:
+       .quad memset
+       .quad 1b
+       .byte X86_FEATURE_REP_GOOD
+       .byte .Lfinal - memset
+       .byte 2b - 1b
        .previous
index 7f5593974e2d0b101c35091b267792943fbe9451..4989f5a8fa9b2fa1cd3903017ae409002a1e8195 100644 (file)
  */
 
 #include <linux/linkage.h>
+#include <asm/dwarf2.h>
 #include <asm/page.h>
 #include <asm/errno.h>
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 
        .text
-       .p2align 4
-.globl __put_user_1
-__put_user_1:
+ENTRY(__put_user_1)
+       CFI_STARTPROC
        GET_THREAD_INFO(%r8)
        cmpq threadinfo_addr_limit(%r8),%rcx
        jae bad_put_user
 1:     movb %dl,(%rcx)
        xorl %eax,%eax
        ret
+       CFI_ENDPROC
+ENDPROC(__put_user_1)
 
-       .p2align 4
-.globl __put_user_2
-__put_user_2:
+ENTRY(__put_user_2)
+       CFI_STARTPROC
        GET_THREAD_INFO(%r8)
        addq $1,%rcx
        jc 20f
@@ -55,10 +56,11 @@ __put_user_2:
        ret
 20:    decq %rcx
        jmp bad_put_user
+       CFI_ENDPROC
+ENDPROC(__put_user_2)
 
-       .p2align 4
-.globl __put_user_4
-__put_user_4:
+ENTRY(__put_user_4)
+       CFI_STARTPROC
        GET_THREAD_INFO(%r8)
        addq $3,%rcx
        jc 30f
@@ -70,10 +72,11 @@ __put_user_4:
        ret
 30:    subq $3,%rcx
        jmp bad_put_user
+       CFI_ENDPROC
+ENDPROC(__put_user_4)
 
-       .p2align 4
-.globl __put_user_8
-__put_user_8:
+ENTRY(__put_user_8)
+       CFI_STARTPROC
        GET_THREAD_INFO(%r8)
        addq $7,%rcx
        jc 40f
@@ -85,10 +88,15 @@ __put_user_8:
        ret
 40:    subq $7,%rcx
        jmp bad_put_user
+       CFI_ENDPROC
+ENDPROC(__put_user_8)
 
 bad_put_user:
+       CFI_STARTPROC
        movq $(-EFAULT),%rax
        ret
+       CFI_ENDPROC
+END(bad_put_user)
 
 .section __ex_table,"a"
        .quad 1b,bad_put_user
diff --git a/arch/x86_64/lib/rwlock.S b/arch/x86_64/lib/rwlock.S
new file mode 100644 (file)
index 0000000..0cde1f8
--- /dev/null
@@ -0,0 +1,38 @@
+/* Slow paths of read/write spinlocks. */
+
+#include <linux/linkage.h>
+#include <asm/rwlock.h>
+#include <asm/alternative-asm.i>
+#include <asm/dwarf2.h>
+
+/* rdi:        pointer to rwlock_t */
+ENTRY(__write_lock_failed)
+       CFI_STARTPROC
+       LOCK_PREFIX
+       addl $RW_LOCK_BIAS,(%rdi)
+1:     rep
+       nop
+       cmpl $RW_LOCK_BIAS,(%rdi)
+       jne 1b
+       LOCK_PREFIX
+       subl $RW_LOCK_BIAS,(%rdi)
+       jnz  __write_lock_failed
+       ret
+       CFI_ENDPROC
+END(__write_lock_failed)
+
+/* rdi:        pointer to rwlock_t */
+ENTRY(__read_lock_failed)
+       CFI_STARTPROC
+       LOCK_PREFIX
+       incl (%rdi)
+1:     rep
+       nop
+       cmpl $1,(%rdi)
+       js 1b
+       LOCK_PREFIX
+       decl (%rdi)
+       js __read_lock_failed
+       ret
+       CFI_ENDPROC
+END(__read_lock_failed)
index 332ea5dff9169627475dbc90f54b4ced9c36d179..0025535cac8d9fa389016d0b79b84519fab9a073 100644 (file)
@@ -1,10 +1,9 @@
-       /*
-        * Save registers before calling assembly functions. This avoids
-        * disturbance of register allocation in some inline assembly constructs.
-        * Copyright 2001,2002 by Andi Kleen, SuSE Labs.
-        * Subject to the GNU public license, v.2. No warranty of any kind.
-        * $Id: thunk.S,v 1.2 2002/03/13 20:06:58 ak Exp $
-        */
+/*
+ * Save registers before calling assembly functions. This avoids
+ * disturbance of register allocation in some inline assembly constructs.
+ * Copyright 2001,2002 by Andi Kleen, SuSE Labs.
+ * Subject to the GNU public license, v.2. No warranty of any kind.
+ */
 
        #include <linux/config.h>
        #include <linux/linkage.h>
@@ -67,33 +66,3 @@ restore_norax:
        RESTORE_ARGS 1
        ret
        CFI_ENDPROC
-
-#ifdef CONFIG_SMP
-/* Support for read/write spinlocks. */
-       .text
-/* rax:        pointer to rwlock_t */  
-ENTRY(__write_lock_failed)
-       lock
-       addl $RW_LOCK_BIAS,(%rax)
-1:     rep
-       nop
-       cmpl $RW_LOCK_BIAS,(%rax)
-       jne 1b
-       lock 
-       subl $RW_LOCK_BIAS,(%rax)
-       jnz  __write_lock_failed
-       ret
-
-/* rax:        pointer to rwlock_t */  
-ENTRY(__read_lock_failed)
-       lock
-       incl (%rax)
-1:     rep
-       nop
-       cmpl $1,(%rax)
-       js 1b
-       lock
-       decl (%rax)
-       js __read_lock_failed
-       ret
-#endif
index 4198798e1469cf92d9b58865e0e88daebe405433..1a17b0733ab5d38ad81ccdf4263e2d58571d9e24 100644 (file)
@@ -40,8 +40,7 @@
 #define PF_RSVD        (1<<3)
 #define PF_INSTR       (1<<4)
 
-#ifdef CONFIG_KPROBES
-ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
+static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
 
 /* Hook to register for page fault notifications */
 int register_page_fault_notifier(struct notifier_block *nb)
@@ -49,11 +48,13 @@ int register_page_fault_notifier(struct notifier_block *nb)
        vmalloc_sync_all();
        return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
 }
+EXPORT_SYMBOL_GPL(register_page_fault_notifier);
 
 int unregister_page_fault_notifier(struct notifier_block *nb)
 {
        return atomic_notifier_chain_unregister(&notify_page_fault_chain, 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)
@@ -67,13 +68,6 @@ static inline int notify_page_fault(enum die_val val, const char *str,
        };
        return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
 }
-#else
-static inline int notify_page_fault(enum die_val val, const char *str,
-                       struct pt_regs *regs, long err, int trap, int sig)
-{
-       return NOTIFY_DONE;
-}
-#endif
 
 void bust_spinlocks(int yes)
 {
@@ -102,7 +96,7 @@ void bust_spinlocks(int yes)
 static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
                                unsigned long error_code)
 { 
-       unsigned char *instr;
+       unsigned char __user *instr;
        int scan_more = 1;
        int prefetch = 0; 
        unsigned char *max_instr;
@@ -111,7 +105,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
        if (error_code & PF_INSTR)
                return 0;
        
-       instr = (unsigned char *)convert_rip_to_linear(current, regs);
+       instr = (unsigned char __user *)convert_rip_to_linear(current, regs);
        max_instr = instr + 15;
 
        if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
@@ -122,7 +116,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
                unsigned char instr_hi;
                unsigned char instr_lo;
 
-               if (__get_user(opcode, instr))
+               if (__get_user(opcode, (char __user *)instr))
                        break; 
 
                instr_hi = opcode & 0xf0; 
@@ -160,7 +154,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
                case 0x00:
                        /* Prefetch instruction is 0x0F0D or 0x0F18 */
                        scan_more = 0;
-                       if (__get_user(opcode, instr)) 
+                       if (__get_user(opcode, (char __user *)instr))
                                break;
                        prefetch = (instr_lo == 0xF) &&
                                (opcode == 0x0D || opcode == 0x18);
@@ -176,7 +170,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
 static int bad_address(void *p) 
 { 
        unsigned long dummy;
-       return __get_user(dummy, (unsigned long *)p);
+       return __get_user(dummy, (unsigned long __user *)p);
 } 
 
 void dump_pagetable(unsigned long address)
index 52fd42c40c8690167db9d8a8bd3b099f99473ac5..3e16fe08150ec6f3bb7a94e7bc6ec12a2e5193a7 100644 (file)
@@ -229,7 +229,6 @@ __init void *early_ioremap(unsigned long addr, unsigned long size)
 
        /* actually usually some more */
        if (size >= LARGE_PAGE_SIZE) { 
-               printk("SMBIOS area too long %lu\n", size);
                return NULL;
        }
        set_pmd(temp_mappings[0].pmd,  __pmd(map | _KERNPG_TABLE | _PAGE_PSE));
@@ -250,12 +249,13 @@ __init void early_iounmap(void *addr, unsigned long size)
 }
 
 static void __meminit
-phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
+phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
 {
-       int i;
+       int i = pmd_index(address);
 
-       for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) {
+       for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) {
                unsigned long entry;
+               pmd_t *pmd = pmd_page + pmd_index(address);
 
                if (address >= end) {
                        if (!after_bootmem)
@@ -263,6 +263,10 @@ phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
                                        set_pmd(pmd, __pmd(0));
                        break;
                }
+
+               if (pmd_val(*pmd))
+                       continue;
+
                entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address;
                entry &= __supported_pte_mask;
                set_pmd(pmd, __pmd(entry));
@@ -272,45 +276,41 @@ phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end)
 static void __meminit
 phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
 {
-       pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address));
-
-       if (pmd_none(*pmd)) {
-               spin_lock(&init_mm.page_table_lock);
-               phys_pmd_init(pmd, address, end);
-               spin_unlock(&init_mm.page_table_lock);
-               __flush_tlb_all();
-       }
+       pmd_t *pmd = pmd_offset(pud,0);
+       spin_lock(&init_mm.page_table_lock);
+       phys_pmd_init(pmd, address, end);
+       spin_unlock(&init_mm.page_table_lock);
+       __flush_tlb_all();
 }
 
-static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
+static void __meminit phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end)
 { 
-       long i = pud_index(address);
+       int i = pud_index(addr);
 
-       pud = pud + i;
 
-       if (after_bootmem && pud_val(*pud)) {
-               phys_pmd_update(pud, address, end);
-               return;
-       }
-
-       for (; i < PTRS_PER_PUD; pud++, i++) {
+       for (; i < PTRS_PER_PUD; i++, addr = (addr & PUD_MASK) + PUD_SIZE ) {
                int map; 
-               unsigned long paddr, pmd_phys;
+               unsigned long pmd_phys;
+               pud_t *pud = pud_page + pud_index(addr);
                pmd_t *pmd;
 
-               paddr = (address & PGDIR_MASK) + i*PUD_SIZE;
-               if (paddr >= end)
+               if (addr >= end)
                        break;
 
-               if (!after_bootmem && !e820_any_mapped(paddr, paddr+PUD_SIZE, 0)) {
+               if (!after_bootmem && !e820_any_mapped(addr,addr+PUD_SIZE,0)) {
                        set_pud(pud, __pud(0)); 
                        continue;
                } 
 
+               if (pud_val(*pud)) {
+                       phys_pmd_update(pud, addr, end);
+                       continue;
+               }
+
                pmd = alloc_low_page(&map, &pmd_phys);
                spin_lock(&init_mm.page_table_lock);
                set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
-               phys_pmd_init(pmd, paddr, end);
+               phys_pmd_init(pmd, addr, end);
                spin_unlock(&init_mm.page_table_lock);
                unmap_low_page(map);
        }
@@ -403,69 +403,15 @@ void __cpuinit zap_low_mappings(int cpu)
        __flush_tlb_all();
 }
 
-/* Compute zone sizes for the DMA and DMA32 zones in a node. */
-__init void
-size_zones(unsigned long *z, unsigned long *h,
-          unsigned long start_pfn, unsigned long end_pfn)
-{
-       int i;
-       unsigned long w;
-
-       for (i = 0; i < MAX_NR_ZONES; i++)
-               z[i] = 0;
-
-       if (start_pfn < MAX_DMA_PFN)
-               z[ZONE_DMA] = MAX_DMA_PFN - start_pfn;
-       if (start_pfn < MAX_DMA32_PFN) {
-               unsigned long dma32_pfn = MAX_DMA32_PFN;
-               if (dma32_pfn > end_pfn)
-                       dma32_pfn = end_pfn;
-               z[ZONE_DMA32] = dma32_pfn - start_pfn;
-       }
-       z[ZONE_NORMAL] = end_pfn - start_pfn;
-
-       /* Remove lower zones from higher ones. */
-       w = 0;
-       for (i = 0; i < MAX_NR_ZONES; i++) {
-               if (z[i])
-                       z[i] -= w;
-               w += z[i];
-       }
-
-       /* Compute holes */
-       w = start_pfn;
-       for (i = 0; i < MAX_NR_ZONES; i++) {
-               unsigned long s = w;
-               w += z[i];
-               h[i] = e820_hole_size(s, w);
-       }
-
-       /* Add the space pace needed for mem_map to the holes too. */
-       for (i = 0; i < MAX_NR_ZONES; i++)
-               h[i] += (z[i] * sizeof(struct page)) / PAGE_SIZE;
-
-       /* The 16MB DMA zone has the kernel and other misc mappings.
-          Account them too */
-       if (h[ZONE_DMA]) {
-               h[ZONE_DMA] += dma_reserve;
-               if (h[ZONE_DMA] >= z[ZONE_DMA]) {
-                       printk(KERN_WARNING
-                               "Kernel too large and filling up ZONE_DMA?\n");
-                       h[ZONE_DMA] = z[ZONE_DMA];
-               }
-       }
-}
-
 #ifndef CONFIG_NUMA
 void __init paging_init(void)
 {
-       unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES];
-
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = {MAX_DMA_PFN,
+                                                       MAX_DMA32_PFN,
+                                                       end_pfn};
        memory_present(0, 0, end_pfn);
        sparse_init();
-       size_zones(zones, holes, 0, end_pfn);
-       free_area_init_node(0, NODE_DATA(0), zones,
-                           __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes);
+       free_area_init_nodes(max_zone_pfns);
 }
 #endif
 
@@ -597,12 +543,6 @@ void __init mem_init(void)
 
        pci_iommu_alloc();
 
-       /* How many end-of-memory variables you have, grandma! */
-       max_low_pfn = end_pfn;
-       max_pfn = end_pfn;
-       num_physpages = end_pfn;
-       high_memory = (void *) __va(end_pfn * PAGE_SIZE);
-
        /* clear the zero-page */
        memset(empty_zero_page, 0, PAGE_SIZE);
 
@@ -614,7 +554,8 @@ void __init mem_init(void)
 #else
        totalram_pages = free_all_bootmem();
 #endif
-       reservedpages = end_pfn - totalram_pages - e820_hole_size(0, end_pfn);
+       reservedpages = end_pfn - totalram_pages -
+                                       absent_pages_in_range(0, end_pfn);
 
        after_bootmem = 1;
 
@@ -714,8 +655,10 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
 #else                  
        reserve_bootmem(phys, len);    
 #endif
-       if (phys+len <= MAX_DMA_PFN*PAGE_SIZE)
+       if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
                dma_reserve += len / PAGE_SIZE;
+               set_dma_reserve(dma_reserve);
+       }
 }
 
 int kern_addr_valid(unsigned long addr) 
index 7c45c2d2b8b28780e4338f3317523dd2dca136b8..b5b8dba28b4efa43000510ad924a83cc97a95fd4 100644 (file)
@@ -54,6 +54,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
 
        nodes_clear(nodes_parsed);
 
+       if (!early_pci_allowed())
+               return -1;
+
        nb = find_northbridge(); 
        if (nb < 0) 
                return nb;
@@ -146,6 +149,9 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end)
                
                nodes[nodeid].start = base; 
                nodes[nodeid].end = limit;
+               e820_register_active_regions(nodeid,
+                               nodes[nodeid].start >> PAGE_SHIFT,
+                               nodes[nodeid].end >> PAGE_SHIFT);
 
                prevbase = base;
 
index b2fac14baac0fc151838b32ad54f6eaf741b8047..829a008bd39b75a95eec6dfb66a46d4497459a48 100644 (file)
@@ -161,7 +161,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
                                         bootmap_start >> PAGE_SHIFT, 
                                         start_pfn, end_pfn); 
 
-       e820_bootmem_free(NODE_DATA(nodeid), start, end);
+       free_bootmem_with_active_regions(nodeid, end);
 
        reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); 
        reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages<<PAGE_SHIFT);
@@ -175,13 +175,11 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
 void __init setup_node_zones(int nodeid)
 { 
        unsigned long start_pfn, end_pfn, memmapsize, limit;
-       unsigned long zones[MAX_NR_ZONES];
-       unsigned long holes[MAX_NR_ZONES];
 
        start_pfn = node_start_pfn(nodeid);
        end_pfn = node_end_pfn(nodeid);
 
-       Dprintk(KERN_INFO "Setting up node %d %lx-%lx\n",
+       Dprintk(KERN_INFO "Setting up memmap for node %d %lx-%lx\n",
                nodeid, start_pfn, end_pfn);
 
        /* Try to allocate mem_map at end to not fill up precious <4GB
@@ -195,10 +193,6 @@ void __init setup_node_zones(int nodeid)
                                round_down(limit - memmapsize, PAGE_SIZE), 
                                limit);
 #endif
-
-       size_zones(zones, holes, start_pfn, end_pfn);
-       free_area_init_node(nodeid, NODE_DATA(nodeid), zones,
-                           start_pfn, holes);
 } 
 
 void __init numa_init_array(void)
@@ -225,7 +219,7 @@ void __init numa_init_array(void)
 int numa_fake __initdata = 0;
 
 /* Numa emulation */
-static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
+static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
 {
        int i;
        struct bootnode nodes[MAX_NUMNODES];
@@ -259,8 +253,11 @@ static int numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
                printk(KERN_ERR "No NUMA hash function found. Emulation disabled.\n");
                return -1;
        }
-       for_each_online_node(i)
+       for_each_online_node(i) {
+               e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
+                                               nodes[i].end >> PAGE_SHIFT);
                setup_node_bootmem(i, nodes[i].start, nodes[i].end);
+       }
        numa_init_array();
        return 0;
 }
@@ -299,6 +296,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
        for (i = 0; i < NR_CPUS; i++)
                numa_set_node(i, 0);
        node_to_cpumask[0] = cpumask_of_cpu(0);
+       e820_register_active_regions(0, start_pfn, end_pfn);
        setup_node_bootmem(0, start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT);
 }
 
@@ -340,17 +338,23 @@ static void __init arch_sparse_init(void)
 void __init paging_init(void)
 { 
        int i;
+       unsigned long max_zone_pfns[MAX_NR_ZONES] = { MAX_DMA_PFN,
+               MAX_DMA32_PFN,
+               end_pfn};
 
        arch_sparse_init();
 
        for_each_online_node(i) {
                setup_node_zones(i); 
        }
+
+       free_area_init_nodes(max_zone_pfns);
 } 
 
-/* [numa=off] */
-__init int numa_setup(char *opt) 
+static __init int numa_setup(char *opt)
 { 
+       if (!opt)
+               return -EINVAL;
        if (!strncmp(opt,"off",3))
                numa_off = 1;
 #ifdef CONFIG_NUMA_EMU
@@ -366,9 +370,11 @@ __init int numa_setup(char *opt)
        if (!strncmp(opt,"hotadd=", 7))
                hotadd_percent = simple_strtoul(opt+7, NULL, 10);
 #endif
-       return 1;
+       return 0;
 } 
 
+early_param("numa", numa_setup);
+
 /*
  * Setup early cpu_to_node.
  *
index 2685b1f3671c4f9fea8acdd8c1fcf42507b8d8e4..3e231d762aaa8527d112687c711747f98f4bac83 100644 (file)
@@ -108,8 +108,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);
-       pgprot_val(ref_prot) |= _PAGE_PSE;
        large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, ref_prot);
+       large_pte = pte_mkhuge(large_pte);
        set_pte((pte_t *)pmd, large_pte);
 }      
 
@@ -119,32 +119,28 @@ __change_page_attr(unsigned long address, unsigned long pfn, pgprot_t prot,
 { 
        pte_t *kpte; 
        struct page *kpte_page;
-       unsigned kpte_flags;
        pgprot_t ref_prot2;
        kpte = lookup_address(address);
        if (!kpte) return 0;
        kpte_page = virt_to_page(((unsigned long)kpte) & PAGE_MASK);
-       kpte_flags = pte_val(*kpte); 
        if (pgprot_val(prot) != pgprot_val(ref_prot)) { 
-               if ((kpte_flags & _PAGE_PSE) == 0) { 
+               if (!pte_huge(*kpte)) {
                        set_pte(kpte, pfn_pte(pfn, prot));
                } else {
                        /*
                         * split_large_page will take the reference for this
                         * change_page_attr on the split page.
                         */
-
                        struct page *split;
-                       ref_prot2 = __pgprot(pgprot_val(pte_pgprot(*lookup_address(address))) & ~(1<<_PAGE_BIT_PSE));
-
+                       ref_prot2 = pte_pgprot(pte_clrhuge(*kpte));
                        split = split_large_page(address, prot, ref_prot2);
                        if (!split)
                                return -ENOMEM;
-                       set_pte(kpte,mk_pte(split, ref_prot2));
+                       set_pte(kpte, mk_pte(split, ref_prot2));
                        kpte_page = split;
-               }       
+               }
                page_private(kpte_page)++;
-       } else if ((kpte_flags & _PAGE_PSE) == 0) { 
+       } else if (!pte_huge(*kpte)) {
                set_pte(kpte, pfn_pte(pfn, ref_prot));
                BUG_ON(page_private(kpte_page) == 0);
                page_private(kpte_page)--;
@@ -190,10 +186,12 @@ int change_page_attr_addr(unsigned long address, int numpages, pgprot_t prot)
                 * lowmem */
                if (__pa(address) < KERNEL_TEXT_SIZE) {
                        unsigned long addr2;
-                       pgprot_t prot2 = prot;
+                       pgprot_t prot2;
                        addr2 = __START_KERNEL_map + __pa(address);
-                       pgprot_val(prot2) &= ~_PAGE_NX;
-                       err = __change_page_attr(addr2, pfn, prot2, PAGE_KERNEL_EXEC);
+                       /* Make sure the kernel mappings stay executable */
+                       prot2 = pte_pgprot(pte_mkexec(pfn_pte(0, prot)));
+                       err = __change_page_attr(addr2, pfn, prot2,
+                                                PAGE_KERNEL_EXEC);
                } 
        }       
        up_write(&init_mm.mmap_sem); 
index 502fce65e96ae246986e4b767b0e10897733b71c..f8c04d6935c922725d64ddf97178826f1b3e27cd 100644 (file)
@@ -21,6 +21,8 @@
 #include <asm/numa.h>
 #include <asm/e820.h>
 
+int acpi_numa __initdata;
+
 #if (defined(CONFIG_ACPI_HOTPLUG_MEMORY) || \
        defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)) \
                && !defined(CONFIG_MEMORY_HOTPLUG)
@@ -91,6 +93,7 @@ static __init void bad_srat(void)
                apicid_to_node[i] = NUMA_NO_NODE;
        for (i = 0; i < MAX_NUMNODES; i++)
                nodes_add[i].start = nodes[i].end = 0;
+       remove_all_active_ranges();
 }
 
 static __init inline int srat_disabled(void)
@@ -173,7 +176,7 @@ static int hotadd_enough_memory(struct bootnode *nd)
 
        if (mem < 0)
                return 0;
-       allowed = (end_pfn - e820_hole_size(0, end_pfn)) * PAGE_SIZE;
+       allowed = (end_pfn - absent_pages_in_range(0, end_pfn)) * PAGE_SIZE;
        allowed = (allowed / 100) * hotadd_percent;
        if (allocated + mem > allowed) {
                unsigned long range;
@@ -223,8 +226,10 @@ static int reserve_hotadd(int node, unsigned long start, unsigned long end)
        }
 
        /* This check might be a bit too strict, but I'm keeping it for now. */
-       if (e820_hole_size(s_pfn, e_pfn) != e_pfn - s_pfn) {
-               printk(KERN_ERR "SRAT: Hotplug area has existing memory\n");
+       if (absent_pages_in_range(s_pfn, e_pfn) != e_pfn - s_pfn) {
+               printk(KERN_ERR
+                       "SRAT: Hotplug area %lu -> %lu has existing memory\n",
+                       s_pfn, e_pfn);
                return -1;
        }
 
@@ -317,6 +322,10 @@ acpi_numa_memory_affinity_init(struct acpi_table_memory_affinity *ma)
 
        printk(KERN_INFO "SRAT: Node %u PXM %u %Lx-%Lx\n", node, pxm,
               nd->start, nd->end);
+       e820_register_active_regions(node, nd->start >> PAGE_SHIFT,
+                                               nd->end >> PAGE_SHIFT);
+       push_node_boundaries(node, nd->start >> PAGE_SHIFT,
+                                               nd->end >> PAGE_SHIFT);
 
 #ifdef RESERVE_HOTADD
        if (ma->flags.hot_pluggable && reserve_hotadd(node, start, end) < 0) {
@@ -341,13 +350,13 @@ static int nodes_cover_memory(void)
                unsigned long s = nodes[i].start >> PAGE_SHIFT;
                unsigned long e = nodes[i].end >> PAGE_SHIFT;
                pxmram += e - s;
-               pxmram -= e820_hole_size(s, e);
+               pxmram -= absent_pages_in_range(s, e);
                pxmram -= nodes_add[i].end - nodes_add[i].start;
                if ((long)pxmram < 0)
                        pxmram = 0;
        }
 
-       e820ram = end_pfn - e820_hole_size(0, end_pfn);
+       e820ram = end_pfn - absent_pages_in_range(0, end_pfn);
        /* We seem to lose 3 pages somewhere. Allow a bit of slack. */
        if ((long)(e820ram - pxmram) >= 1*1024*1024) {
                printk(KERN_ERR
index a3f6ad570179d9a511a242a176a08922da3175bf..1eb18f421edff11924187e8242781bd68116a168 100644 (file)
@@ -9,7 +9,7 @@ obj-y           := i386.o
 obj-$(CONFIG_PCI_DIRECT)+= direct.o
 obj-y          += fixup.o init.o
 obj-$(CONFIG_ACPI)     += acpi.o
-obj-y                  += legacy.o irq.o common.o
+obj-y                  += legacy.o irq.o common.o early.o
 # mmconfig has a 64bit special
 obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o direct.o
 
@@ -23,3 +23,4 @@ common-y += ../../i386/pci/common.o
 fixup-y  += ../../i386/pci/fixup.o
 i386-y  += ../../i386/pci/i386.o
 init-y += ../../i386/pci/init.o
+early-y += ../../i386/pci/early.o
index 3c55c76c6fd5de3d262e20fd7727653cc6849750..7732f4254d21810a4c5441278032169bf59f7e36 100644 (file)
@@ -156,15 +156,45 @@ static __init void unreachable_devices(void)
                        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 %x:%x\n",
-                                       k, i);
+                               printk(KERN_NOTICE "PCI: No mmconfig possible"
+                                      " on device %02x:%02x\n", k, i);
                        }
                }
        }
 }
 
-void __init pci_mmcfg_init(void)
+static __init void 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++) {
+               num_buses = pci_mmcfg_config[i].end_bus_number -
+                   pci_mmcfg_config[i].start_bus_number + 1;
+               res->name = names;
+               snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u",
+                       pci_mmcfg_config[i].pci_segment_group_number);
+               res->start = pci_mmcfg_config[i].base_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;
+       }
+}
+
+void __init pci_mmcfg_init(int type)
 {
        int i;
 
@@ -177,7 +207,9 @@ void __init pci_mmcfg_init(void)
            (pci_mmcfg_config[0].base_address == 0))
                return;
 
-       if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
+       /* 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].base_address,
                        pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
                        E820_RESERVED)) {
                printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not E820-reserved\n",
@@ -186,7 +218,6 @@ void __init pci_mmcfg_init(void)
                return;
        }
 
-       /* RED-PEN i386 doesn't do _nocache right now */
        pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
        if (pci_mmcfg_virt == NULL) {
                printk("PCI: Can not allocate memory for mmconfig structures\n");
@@ -205,6 +236,7 @@ void __init pci_mmcfg_init(void)
        }
 
        unreachable_devices();
+       pci_mmcfg_insert_resources();
 
        raw_pci_ops = &pci_mmcfg;
        pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
index 265f7a830619ef1e5de60bfe1179fa9d3a002229..2b4ef2b89b8d74b376a2011b5455039fd3730e20 100644 (file)
@@ -217,7 +217,7 @@ static int blk_trace_remove(request_queue_t *q)
 
 static int blk_dropped_open(struct inode *inode, struct file *filp)
 {
-       filp->private_data = inode->u.generic_ip;
+       filp->private_data = inode->i_private;
 
        return 0;
 }
index c26c08b368297897f6a07bb86bfb02db3212b3ce..bdb9c8b78ed8afe1a5fd794ce204bef0b60e8d01 100644 (file)
@@ -308,7 +308,6 @@ static struct i2c_algo_bit_data ioc_data = {
        .getsda         = ioc_getsda,
        .getscl         = ioc_getscl,
        .udelay         = 80,
-       .mdelay         = 80,
        .timeout        = 100
 };
 
index 6809c283ec5865ed7183570dbe5814fa7e9bf5a4..6342e612c203726514be32d5ab4e97ecf579f552 100644 (file)
@@ -293,7 +293,7 @@ static u32 acpi_ec_smb_func(struct i2c_adapter *adapter)
                I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC);
 }
 
-static struct i2c_algorithm acpi_ec_smbus_algorithm = {
+static const struct i2c_algorithm acpi_ec_smbus_algorithm = {
        .smbus_xfer = acpi_ec_smb_access,
        .functionality = acpi_ec_smb_func,
 };
index 507f051d1cefd437634454809aa69c748f256a0d..20beea778ea2d929a7efceec03a3fe60f6f9ec12 100644 (file)
@@ -1079,7 +1079,7 @@ acpi_status acpi_os_purge_cache(acpi_cache_t * cache)
 
 acpi_status acpi_os_delete_cache(acpi_cache_t * cache)
 {
-       (void)kmem_cache_destroy(cache);
+       kmem_cache_destroy(cache);
        return (AE_OK);
 }
 
index c3b8dc98b8a739812f78b5311b38bf18d671a8c7..d26644a59537f5a708226652f7a82edc713ed216 100644 (file)
@@ -16,7 +16,7 @@ extern int cpu_dev_init(void);
 extern int attribute_container_init(void);
 
 extern int bus_add_device(struct device * dev);
-extern void bus_attach_device(struct device * dev);
+extern int bus_attach_device(struct device * dev);
 extern void bus_remove_device(struct device * dev);
 extern struct bus_type *get_bus(struct bus_type * bus);
 extern void put_bus(struct bus_type * bus);
index 2e954d07175a5c6d067531ac23d155c1a24d2d8d..12173d16bea7332b9b76e8f19d6568dc01c5a2fd 100644 (file)
@@ -371,12 +371,20 @@ int bus_add_device(struct device * dev)
        if (bus) {
                pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
                error = device_add_attrs(bus, dev);
-               if (!error) {
-                       sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
-                       sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "subsystem");
-                       sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
-               }
+               if (error)
+                       goto out;
+               error = sysfs_create_link(&bus->devices.kobj,
+                                               &dev->kobj, dev->bus_id);
+               if (error)
+                       goto out;
+               error = sysfs_create_link(&dev->kobj,
+                               &dev->bus->subsys.kset.kobj, "subsystem");
+               if (error)
+                       goto out;
+               error = sysfs_create_link(&dev->kobj,
+                               &dev->bus->subsys.kset.kobj, "bus");
        }
+out:
        return error;
 }
 
@@ -384,16 +392,24 @@ int bus_add_device(struct device * dev)
  *     bus_attach_device - add device to bus
  *     @dev:   device tried to attach to a driver
  *
+ *     - Add device to bus's list of devices.
  *     - Try to attach to driver.
  */
-void bus_attach_device(struct device * dev)
+int bus_attach_device(struct device * dev)
 {
-       struct bus_type * bus = dev->bus;
+       struct bus_type *bus = dev->bus;
+       int ret = 0;
 
        if (bus) {
-               device_attach(dev);
-               klist_add_tail(&dev->knode_bus, &bus->klist_devices);
+               dev->is_registered = 1;
+               ret = device_attach(dev);
+               if (ret >= 0) {
+                       klist_add_tail(&dev->knode_bus, &bus->klist_devices);
+                       ret = 0;
+               } else
+                       dev->is_registered = 0;
        }
+       return ret;
 }
 
 /**
@@ -412,7 +428,8 @@ void bus_remove_device(struct device * dev)
                sysfs_remove_link(&dev->kobj, "bus");
                sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
                device_remove_attrs(dev->bus, dev);
-               klist_remove(&dev->knode_bus);
+               dev->is_registered = 0;
+               klist_del(&dev->knode_bus);
                pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
                device_release_driver(dev);
                put_bus(dev->bus);
@@ -455,10 +472,17 @@ static void driver_remove_attrs(struct bus_type * bus, struct device_driver * dr
  * Thanks to drivers making their tables __devinit, we can't allow manual
  * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled.
  */
-static void add_bind_files(struct device_driver *drv)
+static int __must_check add_bind_files(struct device_driver *drv)
 {
-       driver_create_file(drv, &driver_attr_unbind);
-       driver_create_file(drv, &driver_attr_bind);
+       int ret;
+
+       ret = driver_create_file(drv, &driver_attr_unbind);
+       if (ret == 0) {
+               ret = driver_create_file(drv, &driver_attr_bind);
+               if (ret)
+                       driver_remove_file(drv, &driver_attr_unbind);
+       }
+       return ret;
 }
 
 static void remove_bind_files(struct device_driver *drv)
@@ -467,7 +491,7 @@ static void remove_bind_files(struct device_driver *drv)
        driver_remove_file(drv, &driver_attr_unbind);
 }
 #else
-static inline void add_bind_files(struct device_driver *drv) {}
+static inline int add_bind_files(struct device_driver *drv) { return 0; }
 static inline void remove_bind_files(struct device_driver *drv) {}
 #endif
 
@@ -476,7 +500,7 @@ static inline void remove_bind_files(struct device_driver *drv) {}
  *     @drv:   driver.
  *
  */
-int bus_add_driver(struct device_driver * drv)
+int bus_add_driver(struct device_driver *drv)
 {
        struct bus_type * bus = get_bus(drv->bus);
        int error = 0;
@@ -484,27 +508,39 @@ int bus_add_driver(struct device_driver * drv)
        if (bus) {
                pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
                error = kobject_set_name(&drv->kobj, "%s", drv->name);
-               if (error) {
-                       put_bus(bus);
-                       return error;
-               }
+               if (error)
+                       goto out_put_bus;
                drv->kobj.kset = &bus->drivers;
-               if ((error = kobject_register(&drv->kobj))) {
-                       put_bus(bus);
-                       return error;
-               }
+               if ((error = kobject_register(&drv->kobj)))
+                       goto out_put_bus;
 
-               driver_attach(drv);
+               error = driver_attach(drv);
+               if (error)
+                       goto out_unregister;
                klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
                module_add_driver(drv->owner, drv);
 
-               driver_add_attrs(bus, drv);
-               add_bind_files(drv);
+               error = driver_add_attrs(bus, drv);
+               if (error) {
+                       /* How the hell do we get out of this pickle? Give up */
+                       printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
+                               __FUNCTION__, drv->name);
+               }
+               error = add_bind_files(drv);
+               if (error) {
+                       /* Ditto */
+                       printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
+                               __FUNCTION__, drv->name);
+               }
        }
        return error;
+out_unregister:
+       kobject_unregister(&drv->kobj);
+out_put_bus:
+       put_bus(bus);
+       return error;
 }
 
-
 /**
  *     bus_remove_driver - delete driver from bus's knowledge.
  *     @drv:   driver.
@@ -530,16 +566,21 @@ void bus_remove_driver(struct device_driver * drv)
 
 
 /* Helper for bus_rescan_devices's iter */
-static int bus_rescan_devices_helper(struct device *dev, void *data)
+static int __must_check bus_rescan_devices_helper(struct device *dev,
+                                               void *data)
 {
+       int ret = 0;
+
        if (!dev->driver) {
                if (dev->parent)        /* Needed for USB */
                        down(&dev->parent->sem);
-               device_attach(dev);
+               ret = device_attach(dev);
                if (dev->parent)
                        up(&dev->parent->sem);
+               if (ret > 0)
+                       ret = 0;
        }
-       return 0;
+       return ret < 0 ? ret : 0;
 }
 
 /**
@@ -550,9 +591,9 @@ static int bus_rescan_devices_helper(struct device *dev, void *data)
  * attached and rescan it against existing drivers to see if it matches
  * any by calling device_attach() for the unbound devices.
  */
-void bus_rescan_devices(struct bus_type * bus)
+int bus_rescan_devices(struct bus_type * bus)
 {
-       bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);
+       return bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);
 }
 
 /**
@@ -564,7 +605,7 @@ void bus_rescan_devices(struct bus_type * bus)
  * to use if probing criteria changed during a devices lifetime and
  * driver attachment should change accordingly.
  */
-void device_reprobe(struct device *dev)
+int device_reprobe(struct device *dev)
 {
        if (dev->driver) {
                if (dev->parent)        /* Needed for USB */
@@ -573,14 +614,14 @@ void device_reprobe(struct device *dev)
                if (dev->parent)
                        up(&dev->parent->sem);
        }
-
-       bus_rescan_devices_helper(dev, NULL);
+       return bus_rescan_devices_helper(dev, NULL);
 }
 EXPORT_SYMBOL_GPL(device_reprobe);
 
-struct bus_type * get_bus(struct bus_type * bus)
+struct bus_type *get_bus(struct bus_type *bus)
 {
-       return bus ? container_of(subsys_get(&bus->subsys), struct bus_type, subsys) : NULL;
+       return bus ? container_of(subsys_get(&bus->subsys),
+                               struct bus_type, subsys) : NULL;
 }
 
 void put_bus(struct bus_type * bus)
@@ -655,22 +696,6 @@ static void klist_devices_put(struct klist_node *n)
        put_device(dev);
 }
 
-static void klist_drivers_get(struct klist_node *n)
-{
-       struct device_driver *drv = container_of(n, struct device_driver,
-                                                knode_bus);
-
-       get_driver(drv);
-}
-
-static void klist_drivers_put(struct klist_node *n)
-{
-       struct device_driver *drv = container_of(n, struct device_driver,
-                                                knode_bus);
-
-       put_driver(drv);
-}
-
 /**
  *     bus_register - register a bus with the system.
  *     @bus:   bus.
@@ -706,7 +731,7 @@ int bus_register(struct bus_type * bus)
                goto bus_drivers_fail;
 
        klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
-       klist_init(&bus->klist_drivers, klist_drivers_get, klist_drivers_put);
+       klist_init(&bus->klist_drivers, NULL, NULL);
        bus_add_attrs(bus);
 
        pr_debug("bus type '%s' registered\n", bus->name);
index de8908320f235f0d92b9a21b7cea4b9ea96375c7..b06b0e2b9c62b536a321d12295988af5801012b3 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/slab.h>
 #include "base.h"
 
+extern struct subsystem devices_subsys;
+
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
 #define to_class(obj) container_of(obj, struct class, subsys.kset.kobj)
 
@@ -197,7 +199,7 @@ static int class_device_create_uevent(struct class_device *class_dev,
  * Note, the pointer created here is to be destroyed when finished by
  * making a call to class_destroy().
  */
-struct class *class_create(struct module *owner, char *name)
+struct class *class_create(struct module *owner, const char *name)
 {
        struct class *cls;
        int retval;
@@ -361,7 +363,7 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp,
        pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
 
        if (class_dev->dev) {
-               /* add physical device, backing this device  */
+               /* add device, backing this class device (deprecated) */
                struct device *dev = class_dev->dev;
                char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
 
@@ -679,7 +681,8 @@ int class_device_register(struct class_device *class_dev)
 struct class_device *class_device_create(struct class *cls,
                                         struct class_device *parent,
                                         dev_t devt,
-                                        struct device *device, char *fmt, ...)
+                                        struct device *device,
+                                        const char *fmt, ...)
 {
        va_list args;
        struct class_device *class_dev = NULL;
@@ -839,6 +842,7 @@ int class_interface_register(struct class_interface *class_intf)
 {
        struct class *parent;
        struct class_device *class_dev;
+       struct device *dev;
 
        if (!class_intf || !class_intf->class)
                return -ENODEV;
@@ -853,6 +857,10 @@ int class_interface_register(struct class_interface *class_intf)
                list_for_each_entry(class_dev, &parent->children, node)
                        class_intf->add(class_dev, class_intf);
        }
+       if (class_intf->add_dev) {
+               list_for_each_entry(dev, &parent->devices, node)
+                       class_intf->add_dev(dev, class_intf);
+       }
        up(&parent->sem);
 
        return 0;
@@ -862,6 +870,7 @@ void class_interface_unregister(struct class_interface *class_intf)
 {
        struct class * parent = class_intf->class;
        struct class_device *class_dev;
+       struct device *dev;
 
        if (!parent)
                return;
@@ -872,12 +881,31 @@ void class_interface_unregister(struct class_interface *class_intf)
                list_for_each_entry(class_dev, &parent->children, node)
                        class_intf->remove(class_dev, class_intf);
        }
+       if (class_intf->remove_dev) {
+               list_for_each_entry(dev, &parent->devices, node)
+                       class_intf->remove_dev(dev, class_intf);
+       }
        up(&parent->sem);
 
        class_put(parent);
 }
 
+int virtual_device_parent(struct device *dev)
+{
+       if (!dev->class)
+               return -ENODEV;
+
+       if (!dev->class->virtual_dir) {
+               static struct kobject *virtual_dir = NULL;
+
+               if (!virtual_dir)
+                       virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
+               dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
+       }
 
+       dev->kobj.parent = dev->class->virtual_dir;
+       return 0;
+}
 
 int __init classes_init(void)
 {
index be6b5bc0677d545c0f79efd659f98d268fffb200..b224bb43ff638f812694efe1e4c8eaa5bbd47967 100644 (file)
@@ -3,6 +3,8 @@
  *
  * Copyright (c) 2002-3 Patrick Mochel
  * Copyright (c) 2002-3 Open Source Development Labs
+ * Copyright (c) 2006 Greg Kroah-Hartman <gregkh@suse.de>
+ * Copyright (c) 2006 Novell, Inc.
  *
  * This file is released under the GPLv2
  *
@@ -92,6 +94,8 @@ static void device_release(struct kobject * kobj)
 
        if (dev->release)
                dev->release(dev);
+       else if (dev->class && dev->class->dev_release)
+               dev->class->dev_release(dev);
        else {
                printk(KERN_ERR "Device '%s' does not have a release() function, "
                        "it is broken and must be fixed.\n",
@@ -149,17 +153,21 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
                               "MINOR=%u", MINOR(dev->devt));
        }
 
-       /* add bus name of physical device */
+       /* add bus name (same as SUBSYSTEM, deprecated) */
        if (dev->bus)
                add_uevent_var(envp, num_envp, &i,
                               buffer, buffer_size, &length,
                               "PHYSDEVBUS=%s", dev->bus->name);
 
-       /* add driver name of physical device */
-       if (dev->driver)
+       /* add driver name (PHYSDEV* values are deprecated)*/
+       if (dev->driver) {
+               add_uevent_var(envp, num_envp, &i,
+                              buffer, buffer_size, &length,
+                              "DRIVER=%s", dev->driver->name);
                add_uevent_var(envp, num_envp, &i,
                               buffer, buffer_size, &length,
                               "PHYSDEVDRIVER=%s", dev->driver->name);
+       }
 
        /* terminate, set to next free slot, shrink available space */
        envp[i] = NULL;
@@ -177,6 +185,15 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
                }
        }
 
+       if (dev->class && dev->class->dev_uevent) {
+               /* have the class specific function add its stuff */
+               retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size);
+                       if (retval) {
+                               pr_debug("%s - dev_uevent() returned %d\n",
+                                        __FUNCTION__, retval);
+               }
+       }
+
        return retval;
 }
 
@@ -193,6 +210,72 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
+static int device_add_groups(struct device *dev)
+{
+       int i;
+       int error = 0;
+
+       if (dev->groups) {
+               for (i = 0; dev->groups[i]; i++) {
+                       error = sysfs_create_group(&dev->kobj, dev->groups[i]);
+                       if (error) {
+                               while (--i >= 0)
+                                       sysfs_remove_group(&dev->kobj, dev->groups[i]);
+                               goto out;
+                       }
+               }
+       }
+out:
+       return error;
+}
+
+static void device_remove_groups(struct device *dev)
+{
+       int i;
+       if (dev->groups) {
+               for (i = 0; dev->groups[i]; i++) {
+                       sysfs_remove_group(&dev->kobj, dev->groups[i]);
+               }
+       }
+}
+
+static int device_add_attrs(struct device *dev)
+{
+       struct class *class = dev->class;
+       int error = 0;
+       int i;
+
+       if (!class)
+               return 0;
+
+       if (class->dev_attrs) {
+               for (i = 0; attr_name(class->dev_attrs[i]); i++) {
+                       error = device_create_file(dev, &class->dev_attrs[i]);
+                       if (error)
+                               break;
+               }
+       }
+       if (error)
+               while (--i >= 0)
+                       device_remove_file(dev, &class->dev_attrs[i]);
+       return error;
+}
+
+static void device_remove_attrs(struct device *dev)
+{
+       struct class *class = dev->class;
+       int i;
+
+       if (!class)
+               return;
+
+       if (class->dev_attrs) {
+               for (i = 0; attr_name(class->dev_attrs[i]); i++)
+                       device_remove_file(dev, &class->dev_attrs[i]);
+       }
+}
+
+
 static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
                        char *buf)
 {
@@ -236,6 +319,32 @@ void device_remove_file(struct device * dev, struct device_attribute * attr)
        }
 }
 
+/**
+ * device_create_bin_file - create sysfs binary attribute file for device.
+ * @dev: device.
+ * @attr: device binary attribute descriptor.
+ */
+int device_create_bin_file(struct device *dev, struct bin_attribute *attr)
+{
+       int error = -EINVAL;
+       if (dev)
+               error = sysfs_create_bin_file(&dev->kobj, attr);
+       return error;
+}
+EXPORT_SYMBOL_GPL(device_create_bin_file);
+
+/**
+ * device_remove_bin_file - remove sysfs binary attribute file
+ * @dev: device.
+ * @attr: device binary attribute descriptor.
+ */
+void device_remove_bin_file(struct device *dev, struct bin_attribute *attr)
+{
+       if (dev)
+               sysfs_remove_bin_file(&dev->kobj, attr);
+}
+EXPORT_SYMBOL_GPL(device_remove_bin_file);
+
 static void klist_children_get(struct klist_node *n)
 {
        struct device *dev = container_of(n, struct device, knode_parent);
@@ -289,12 +398,20 @@ int device_add(struct device *dev)
 {
        struct device *parent = NULL;
        char *class_name = NULL;
+       struct class_interface *class_intf;
        int error = -EINVAL;
 
        dev = get_device(dev);
        if (!dev || !strlen(dev->bus_id))
                goto Error;
 
+       /* if this is a class device, and has no parent, create one */
+       if ((dev->class) && (dev->parent == NULL)) {
+               error = virtual_device_parent(dev);
+               if (error)
+                       goto Error;
+       }
+
        parent = get_device(dev->parent);
 
        pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
@@ -307,6 +424,10 @@ int device_add(struct device *dev)
        if ((error = kobject_add(&dev->kobj)))
                goto Error;
 
+       /* notify platform of device entry */
+       if (platform_notify)
+               platform_notify(dev);
+
        dev->uevent_attr.attr.name = "uevent";
        dev->uevent_attr.attr.mode = S_IWUSR;
        if (dev->driver)
@@ -340,12 +461,17 @@ int device_add(struct device *dev)
                                  "subsystem");
                sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj,
                                  dev->bus_id);
-
-               sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device");
-               class_name = make_class_name(dev->class->name, &dev->kobj);
-               sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name);
+               if (parent) {
+                       sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device");
+                       class_name = make_class_name(dev->class->name, &dev->kobj);
+                       sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name);
+               }
        }
 
+       if ((error = device_add_attrs(dev)))
+               goto AttrsError;
+       if ((error = device_add_groups(dev)))
+               goto GroupError;
        if ((error = device_pm_add(dev)))
                goto PMError;
        if ((error = bus_add_device(dev)))
@@ -356,15 +482,16 @@ int device_add(struct device *dev)
                klist_add_tail(&dev->knode_parent, &parent->klist_children);
 
        if (dev->class) {
-               /* tie the class to the device */
                down(&dev->class->sem);
+               /* tie the class to the device */
                list_add_tail(&dev->node, &dev->class->devices);
+
+               /* notify any interfaces that the device is here */
+               list_for_each_entry(class_intf, &dev->class->interfaces, node)
+                       if (class_intf->add_dev)
+                               class_intf->add_dev(dev, class_intf);
                up(&dev->class->sem);
        }
-
-       /* notify platform of device entry */
-       if (platform_notify)
-               platform_notify(dev);
  Done:
        kfree(class_name);
        put_device(dev);
@@ -372,6 +499,10 @@ int device_add(struct device *dev)
  BusError:
        device_pm_remove(dev);
  PMError:
+       device_remove_groups(dev);
+ GroupError:
+       device_remove_attrs(dev);
+ AttrsError:
        if (dev->devt_attr) {
                device_remove_file(dev, dev->devt_attr);
                kfree(dev->devt_attr);
@@ -449,6 +580,7 @@ void device_del(struct device * dev)
 {
        struct device * parent = dev->parent;
        char *class_name = NULL;
+       struct class_interface *class_intf;
 
        if (parent)
                klist_del(&dev->knode_parent);
@@ -458,14 +590,23 @@ void device_del(struct device * dev)
                sysfs_remove_link(&dev->kobj, "subsystem");
                sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id);
                class_name = make_class_name(dev->class->name, &dev->kobj);
-               sysfs_remove_link(&dev->kobj, "device");
-               sysfs_remove_link(&dev->parent->kobj, class_name);
+               if (parent) {
+                       sysfs_remove_link(&dev->kobj, "device");
+                       sysfs_remove_link(&dev->parent->kobj, class_name);
+               }
                kfree(class_name);
                down(&dev->class->sem);
+               /* notify any interfaces that the device is now gone */
+               list_for_each_entry(class_intf, &dev->class->interfaces, node)
+                       if (class_intf->remove_dev)
+                               class_intf->remove_dev(dev, class_intf);
+               /* remove the device from the class list */
                list_del_init(&dev->node);
                up(&dev->class->sem);
        }
        device_remove_file(dev, &dev->uevent_attr);
+       device_remove_groups(dev);
+       device_remove_attrs(dev);
 
        /* Notify the platform of the removal, in case they
         * need to do anything...
@@ -579,7 +720,7 @@ static void device_create_release(struct device *dev)
  * been created with a call to class_create().
  */
 struct device *device_create(struct class *class, struct device *parent,
-                            dev_t devt, char *fmt, ...)
+                            dev_t devt, const char *fmt, ...)
 {
        va_list args;
        struct device *dev = NULL;
@@ -587,10 +728,6 @@ struct device *device_create(struct class *class, struct device *parent,
 
        if (class == NULL || IS_ERR(class))
                goto error;
-       if (parent == NULL) {
-               printk(KERN_WARNING "%s does not work yet for NULL parents\n", __FUNCTION__);
-               goto error;
-       }
 
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev) {
@@ -644,3 +781,58 @@ void device_destroy(struct class *class, dev_t devt)
                device_unregister(dev);
 }
 EXPORT_SYMBOL_GPL(device_destroy);
+
+/**
+ * device_rename - renames a device
+ * @dev: the pointer to the struct device to be renamed
+ * @new_name: the new name of the device
+ */
+int device_rename(struct device *dev, char *new_name)
+{
+       char *old_class_name = NULL;
+       char *new_class_name = NULL;
+       char *old_symlink_name = NULL;
+       int error;
+
+       dev = get_device(dev);
+       if (!dev)
+               return -EINVAL;
+
+       pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name);
+
+       if ((dev->class) && (dev->parent))
+               old_class_name = make_class_name(dev->class->name, &dev->kobj);
+
+       if (dev->class) {
+               old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
+               if (!old_symlink_name)
+                       return -ENOMEM;
+               strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE);
+       }
+
+       strlcpy(dev->bus_id, new_name, BUS_ID_SIZE);
+
+       error = kobject_rename(&dev->kobj, new_name);
+
+       if (old_class_name) {
+               new_class_name = make_class_name(dev->class->name, &dev->kobj);
+               if (new_class_name) {
+                       sysfs_create_link(&dev->parent->kobj, &dev->kobj,
+                                         new_class_name);
+                       sysfs_remove_link(&dev->parent->kobj, old_class_name);
+               }
+       }
+       if (dev->class) {
+               sysfs_remove_link(&dev->class->subsys.kset.kobj,
+                                 old_symlink_name);
+               sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj,
+                                 dev->bus_id);
+       }
+       put_device(dev);
+
+       kfree(old_class_name);
+       kfree(new_class_name);
+       kfree(old_symlink_name);
+
+       return error;
+}
index 889c71111239436d1c9f705cfa5f32ff14ba6f0f..b5f43c3e44fa2a5c9d5bf23898ea57472e7b38ae 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/kthread.h>
 
 #include "base.h"
 #include "power/power.h"
  *
  *     This function must be called with @dev->sem held.
  */
-void device_bind_driver(struct device * dev)
+int device_bind_driver(struct device *dev)
 {
-       if (klist_node_attached(&dev->knode_driver))
-               return;
+       int ret;
+
+       if (klist_node_attached(&dev->knode_driver)) {
+               printk(KERN_WARNING "%s: device %s already bound\n",
+                       __FUNCTION__, kobject_name(&dev->kobj));
+               return 0;
+       }
 
        pr_debug("bound device '%s' to driver '%s'\n",
                 dev->bus_id, dev->driver->name);
        klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
-       sysfs_create_link(&dev->driver->kobj, &dev->kobj,
+       ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
                          kobject_name(&dev->kobj));
-       sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
+       if (ret == 0) {
+               ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj,
+                                       "driver");
+               if (ret)
+                       sysfs_remove_link(&dev->driver->kobj,
+                                       kobject_name(&dev->kobj));
+       }
+       return ret;
 }
 
-/**
- *     driver_probe_device - attempt to bind device & driver.
- *     @drv:   driver.
- *     @dev:   device.
- *
- *     First, we call the bus's match function, if one present, which
- *     should compare the device IDs the driver supports with the
- *     device IDs of the device. Note we don't do this ourselves
- *     because we don't know the format of the ID structures, nor what
- *     is to be considered a match and what is not.
- *
- *     This function returns 1 if a match is found, an error if one
- *     occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
- *
- *     This function must be called with @dev->sem held.  When called
- *     for a USB interface, @dev->parent->sem must be held as well.
- */
-int driver_probe_device(struct device_driver * drv, struct device * dev)
+struct stupid_thread_structure {
+       struct device_driver *drv;
+       struct device *dev;
+};
+
+static atomic_t probe_count = ATOMIC_INIT(0);
+static int really_probe(void *void_data)
 {
+       struct stupid_thread_structure *data = void_data;
+       struct device_driver *drv = data->drv;
+       struct device *dev = data->dev;
        int ret = 0;
 
-       if (drv->bus->match && !drv->bus->match(dev, drv))
-               goto Done;
+       atomic_inc(&probe_count);
+       pr_debug("%s: Probing driver %s with device %s\n",
+                drv->bus->name, drv->name, dev->bus_id);
 
-       pr_debug("%s: Matched Device %s with Driver %s\n",
-                drv->bus->name, dev->bus_id, drv->name);
        dev->driver = drv;
        if (dev->bus->probe) {
                ret = dev->bus->probe(dev);
                if (ret) {
                        dev->driver = NULL;
-                       goto ProbeFailed;
+                       goto probe_failed;
                }
        } else if (drv->probe) {
                ret = drv->probe(dev);
                if (ret) {
                        dev->driver = NULL;
-                       goto ProbeFailed;
+                       goto probe_failed;
                }
        }
-       device_bind_driver(dev);
+       if (device_bind_driver(dev)) {
+               printk(KERN_ERR "%s: device_bind_driver(%s) failed\n",
+                       __FUNCTION__, dev->bus_id);
+               /* How does undo a ->probe?  We're screwed. */
+       }
        ret = 1;
        pr_debug("%s: Bound Device %s to Driver %s\n",
                 drv->bus->name, dev->bus_id, drv->name);
-       goto Done;
+       goto done;
 
- ProbeFailed:
+probe_failed:
        if (ret == -ENODEV || ret == -ENXIO) {
                /* Driver matched, but didn't support device
                 * or device not found.
@@ -110,7 +118,71 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
                       "%s: probe of %s failed with error %d\n",
                       drv->name, dev->bus_id, ret);
        }
- Done:
+done:
+       kfree(data);
+       atomic_dec(&probe_count);
+       return ret;
+}
+
+/**
+ * driver_probe_done
+ * Determine if the probe sequence is finished or not.
+ *
+ * Should somehow figure out how to use a semaphore, not an atomic variable...
+ */
+int driver_probe_done(void)
+{
+       pr_debug("%s: probe_count = %d\n", __FUNCTION__,
+                atomic_read(&probe_count));
+       if (atomic_read(&probe_count))
+               return -EBUSY;
+       return 0;
+}
+
+/**
+ * driver_probe_device - attempt to bind device & driver together
+ * @drv: driver to bind a device to
+ * @dev: device to try to bind to the driver
+ *
+ * First, we call the bus's match function, if one present, which should
+ * compare the device IDs the driver supports with the device IDs of the
+ * device. Note we don't do this ourselves because we don't know the
+ * format of the ID structures, nor what is to be considered a match and
+ * what is not.
+ *
+ * This function returns 1 if a match is found, an error if one occurs
+ * (that is not -ENODEV or -ENXIO), and 0 otherwise.
+ *
+ * This function must be called with @dev->sem held.  When called for a
+ * USB interface, @dev->parent->sem must be held as well.
+ */
+int driver_probe_device(struct device_driver * drv, struct device * dev)
+{
+       struct stupid_thread_structure *data;
+       struct task_struct *probe_task;
+       int ret = 0;
+
+       if (!device_is_registered(dev))
+               return -ENODEV;
+       if (drv->bus->match && !drv->bus->match(dev, drv))
+               goto done;
+
+       pr_debug("%s: Matched Device %s with Driver %s\n",
+                drv->bus->name, dev->bus_id, drv->name);
+
+       data = kmalloc(sizeof(*data), GFP_KERNEL);
+       data->drv = drv;
+       data->dev = dev;
+
+       if (drv->multithread_probe) {
+               probe_task = kthread_run(really_probe, data,
+                                        "probe-%s", dev->bus_id);
+               if (IS_ERR(probe_task))
+                       ret = PTR_ERR(probe_task);
+       } else
+               ret = really_probe(data);
+
+done:
        return ret;
 }
 
@@ -139,8 +211,9 @@ int device_attach(struct device * dev)
 
        down(&dev->sem);
        if (dev->driver) {
-               device_bind_driver(dev);
-               ret = 1;
+               ret = device_bind_driver(dev);
+               if (ret == 0)
+                       ret = 1;
        } else
                ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
        up(&dev->sem);
@@ -182,9 +255,9 @@ static int __driver_attach(struct device * dev, void * data)
  *     returns 0 and the @dev->driver is set, we've found a
  *     compatible pair.
  */
-void driver_attach(struct device_driver * drv)
+int driver_attach(struct device_driver * drv)
 {
-       bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
+       return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
 }
 
 /**
index 562600dd540a942a08b49277f06209b016fb8d07..1214cbd17d868bf1613bcf79ee079cabef95ca62 100644 (file)
@@ -142,20 +142,6 @@ void put_driver(struct device_driver * drv)
        kobject_put(&drv->kobj);
 }
 
-static void klist_devices_get(struct klist_node *n)
-{
-       struct device *dev = container_of(n, struct device, knode_driver);
-
-       get_device(dev);
-}
-
-static void klist_devices_put(struct klist_node *n)
-{
-       struct device *dev = container_of(n, struct device, knode_driver);
-
-       put_device(dev);
-}
-
 /**
  *     driver_register - register driver with bus
  *     @drv:   driver to register
@@ -175,7 +161,7 @@ int driver_register(struct device_driver * drv)
            (drv->bus->shutdown && drv->shutdown)) {
                printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
        }
-       klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put);
+       klist_init(&drv->klist_devices, NULL, NULL);
        init_completion(&drv->unloaded);
        return bus_add_driver(drv);
 }
index 5d6c011183f5b7259297276b251f1648580421c7..77bf8826e2f97b9d19cfaad6457df1371e660262 100644 (file)
@@ -602,7 +602,7 @@ firmware_class_exit(void)
        class_unregister(&firmware_class);
 }
 
-module_init(firmware_class_init);
+fs_initcall(firmware_class_init);
 module_exit(firmware_class_exit);
 
 EXPORT_SYMBOL(release_firmware);
index 2b8755db76c6e65f48b7784cb463d6a213238453..940ce41f1887cadef797b3462cb777f239938d46 100644 (file)
@@ -505,12 +505,36 @@ static int platform_match(struct device * dev, struct device_driver * drv)
        return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
 }
 
-static int platform_suspend(struct device * dev, pm_message_t state)
+static int platform_suspend(struct device *dev, pm_message_t mesg)
 {
        int ret = 0;
 
        if (dev->driver && dev->driver->suspend)
-               ret = dev->driver->suspend(dev, state);
+               ret = dev->driver->suspend(dev, mesg);
+
+       return ret;
+}
+
+static int platform_suspend_late(struct device *dev, pm_message_t mesg)
+{
+       struct platform_driver *drv = to_platform_driver(dev->driver);
+       struct platform_device *pdev = container_of(dev, struct platform_device, dev);
+       int ret = 0;
+
+       if (dev->driver && drv->suspend_late)
+               ret = drv->suspend_late(pdev, mesg);
+
+       return ret;
+}
+
+static int platform_resume_early(struct device *dev)
+{
+       struct platform_driver *drv = to_platform_driver(dev->driver);
+       struct platform_device *pdev = container_of(dev, struct platform_device, dev);
+       int ret = 0;
+
+       if (dev->driver && drv->resume_early)
+               ret = drv->resume_early(pdev);
 
        return ret;
 }
@@ -531,6 +555,8 @@ struct bus_type platform_bus_type = {
        .match          = platform_match,
        .uevent         = platform_uevent,
        .suspend        = platform_suspend,
+       .suspend_late   = platform_suspend_late,
+       .resume_early   = platform_resume_early,
        .resume         = platform_resume,
 };
 EXPORT_SYMBOL_GPL(platform_bus_type);
index 826093ef4c7eb0e83cd0fa5fc8564cf6416144ea..020be36705a6827f38bfa15c83a304672b9e9c55 100644 (file)
@@ -38,13 +38,35 @@ int resume_device(struct device * dev)
                dev_dbg(dev,"resuming\n");
                error = dev->bus->resume(dev);
        }
+       if (dev->class && dev->class->resume) {
+               dev_dbg(dev,"class resume\n");
+               error = dev->class->resume(dev);
+       }
        up(&dev->sem);
        TRACE_RESUME(error);
        return error;
 }
 
 
+static int resume_device_early(struct device * dev)
+{
+       int error = 0;
 
+       TRACE_DEVICE(dev);
+       TRACE_RESUME(0);
+       if (dev->bus && dev->bus->resume_early) {
+               dev_dbg(dev,"EARLY resume\n");
+               error = dev->bus->resume_early(dev);
+       }
+       TRACE_RESUME(error);
+       return error;
+}
+
+/*
+ * Resume the devices that have either not gone through
+ * the late suspend, or that did go through it but also
+ * went through the early resume
+ */
 void dpm_resume(void)
 {
        down(&dpm_list_sem);
@@ -74,6 +96,7 @@ void dpm_resume(void)
 
 void device_resume(void)
 {
+       might_sleep();
        down(&dpm_sem);
        dpm_resume();
        up(&dpm_sem);
@@ -83,12 +106,12 @@ EXPORT_SYMBOL_GPL(device_resume);
 
 
 /**
- *     device_power_up_irq - Power on some devices.
+ *     dpm_power_up - Power on some devices.
  *
  *     Walk the dpm_off_irq list and power each device up. This
  *     is used for devices that required they be powered down with
- *     interrupts disabled. As devices are powered on, they are moved to
- *     the dpm_suspended list.
+ *     interrupts disabled. As devices are powered on, they are moved
+ *     to the dpm_active list.
  *
  *     Interrupts must be disabled when calling this.
  */
@@ -99,16 +122,14 @@ void dpm_power_up(void)
                struct list_head * entry = dpm_off_irq.next;
                struct device * dev = to_device(entry);
 
-               get_device(dev);
-               list_move_tail(entry, &dpm_active);
-               resume_device(dev);
-               put_device(dev);
+               list_move_tail(entry, &dpm_off);
+               resume_device_early(dev);
        }
 }
 
 
 /**
- *     device_pm_power_up - Turn on all devices that need special attention.
+ *     device_power_up - Turn on all devices that need special attention.
  *
  *     Power on system devices then devices that required we shut them down
  *     with interrupts disabled.
index 69509e02f703c6a32a9c158f70cf558bf70d77cb..ece136bf97e35d2921b9ac8b1576eb32d53e7252 100644 (file)
@@ -34,6 +34,7 @@ static inline char *suspend_verb(u32 event)
        switch (event) {
        case PM_EVENT_SUSPEND:  return "suspend";
        case PM_EVENT_FREEZE:   return "freeze";
+       case PM_EVENT_PRETHAW:  return "prethaw";
        default:                return "(unknown suspend event)";
        }
 }
@@ -65,7 +66,19 @@ int suspend_device(struct device * dev, pm_message_t state)
 
        dev->power.prev_state = dev->power.power_state;
 
-       if (dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
+       if (dev->class && dev->class->suspend && !dev->power.power_state.event) {
+               dev_dbg(dev, "class %s%s\n",
+                       suspend_verb(state.event),
+                       ((state.event == PM_EVENT_SUSPEND)
+                                       && device_may_wakeup(dev))
+                               ? ", may wakeup"
+                               : ""
+                       );
+               error = dev->class->suspend(dev, state);
+               suspend_report_result(dev->class->suspend, error);
+       }
+
+       if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
                dev_dbg(dev, "%s%s\n",
                        suspend_verb(state.event),
                        ((state.event == PM_EVENT_SUSPEND)
@@ -81,15 +94,42 @@ int suspend_device(struct device * dev, pm_message_t state)
 }
 
 
+/*
+ * This is called with interrupts off, only a single CPU
+ * running. We can't do down() on a semaphore (and we don't
+ * need the protection)
+ */
+static int suspend_device_late(struct device *dev, pm_message_t state)
+{
+       int error = 0;
+
+       if (dev->bus && dev->bus->suspend_late && !dev->power.power_state.event) {
+               dev_dbg(dev, "LATE %s%s\n",
+                       suspend_verb(state.event),
+                       ((state.event == PM_EVENT_SUSPEND)
+                                       && device_may_wakeup(dev))
+                               ? ", may wakeup"
+                               : ""
+                       );
+               error = dev->bus->suspend_late(dev, state);
+               suspend_report_result(dev->bus->suspend_late, error);
+       }
+       return error;
+}
+
 /**
  *     device_suspend - Save state and stop all devices in system.
  *     @state:         Power state to put each device in.
  *
  *     Walk the dpm_active list, call ->suspend() for each device, and move
- *     it to dpm_off.
- *     Check the return value for each. If it returns 0, then we move the
- *     the device to the dpm_off list. If it returns -EAGAIN, we move it to
- *     the dpm_off_irq list. If we get a different error, try and back out.
+ *     it to the dpm_off list.
+ *
+ *     (For historical reasons, if it returns -EAGAIN, that used to mean
+ *     that the device would be called again with interrupts disabled.
+ *     These days, we use the "suspend_late()" callback for that, so we
+ *     print a warning and consider it an error).
+ *
+ *     If we get a different error, try and back out.
  *
  *     If we hit a failure with any of the devices, call device_resume()
  *     above to bring the suspended devices back to life.
@@ -100,6 +140,7 @@ int device_suspend(pm_message_t state)
 {
        int error = 0;
 
+       might_sleep();
        down(&dpm_sem);
        down(&dpm_list_sem);
        while (!list_empty(&dpm_active) && error == 0) {
@@ -115,39 +156,27 @@ int device_suspend(pm_message_t state)
 
                /* Check if the device got removed */
                if (!list_empty(&dev->power.entry)) {
-                       /* Move it to the dpm_off or dpm_off_irq list */
+                       /* Move it to the dpm_off list */
                        if (!error)
                                list_move(&dev->power.entry, &dpm_off);
-                       else if (error == -EAGAIN) {
-                               list_move(&dev->power.entry, &dpm_off_irq);
-                               error = 0;
-                       }
                }
                if (error)
                        printk(KERN_ERR "Could not suspend device %s: "
-                               "error %d\n", kobject_name(&dev->kobj), error);
+                               "error %d%s\n",
+                               kobject_name(&dev->kobj), error,
+                               error == -EAGAIN ? " (please convert to suspend_late)" : "");
                put_device(dev);
        }
        up(&dpm_list_sem);
-       if (error) {
-               /* we failed... before resuming, bring back devices from
-                * dpm_off_irq list back to main dpm_off list, we do want
-                * to call resume() on them, in case they partially suspended
-                * despite returning -EAGAIN
-                */
-               while (!list_empty(&dpm_off_irq)) {
-                       struct list_head * entry = dpm_off_irq.next;
-                       list_move(entry, &dpm_off);
-               }
+       if (error)
                dpm_resume();
-       }
+
        up(&dpm_sem);
        return error;
 }
 
 EXPORT_SYMBOL_GPL(device_suspend);
 
-
 /**
  *     device_power_down - Shut down special devices.
  *     @state:         Power state to enter.
@@ -162,14 +191,17 @@ int device_power_down(pm_message_t state)
        int error = 0;
        struct device * dev;
 
-       list_for_each_entry_reverse(dev, &dpm_off_irq, power.entry) {
-               if ((error = suspend_device(dev, state)))
-                       break;
+       while (!list_empty(&dpm_off)) {
+               struct list_head * entry = dpm_off.prev;
+
+               dev = to_device(entry);
+               error = suspend_device_late(dev, state);
+               if (error)
+                       goto Error;
+               list_move(&dev->power.entry, &dpm_off_irq);
        }
-       if (error)
-               goto Error;
-       if ((error = sysdev_suspend(state)))
-               goto Error;
+
+       error = sysdev_suspend(state);
  Done:
        return error;
  Error:
index 40d7242a07c18325b18539076b6a3918bb9e87ec..2d47517dbe323ea8d498be0babb4c5ddb6649219 100644 (file)
@@ -7,22 +7,29 @@
 #include "power.h"
 
 
+#ifdef CONFIG_PM_SYSFS_DEPRECATED
+
 /**
  *     state - Control current power state of device
  *
  *     show() returns the current power state of the device. '0' indicates
- *     the device is on. Other values (1-3) indicate the device is in a low
+ *     the device is on. Other values (2) indicate the device is in some low
  *     power state.
  *
- *     store() sets the current power state, which is an integer value
- *     between 0-3. If the device is on ('0'), and the value written is
- *     greater than 0, then the device is placed directly into the low-power
- *     state (via its driver's ->suspend() method).
- *     If the device is currently in a low-power state, and the value is 0,
- *     the device is powered back on (via the ->resume() method).
- *     If the device is in a low-power state, and a different low-power state
- *     is requested, the device is first resumed, then suspended into the new
- *     low-power state.
+ *     store() sets the current power state, which is an integer valued
+ *     0, 2, or 3.  Devices with bus.suspend_late(), or bus.resume_early()
+ *     methods fail this operation; those methods couldn't be called.
+ *     Otherwise,
+ *
+ *     - If the recorded dev->power.power_state.event matches the
+ *       target value, nothing is done.
+ *     - If the recorded event code is nonzero, the device is reactivated
+ *       by calling bus.resume() and/or class.resume().
+ *     - If the target value is nonzero, the device is suspended by
+ *       calling class.suspend() and/or bus.suspend() with event code
+ *       PM_EVENT_SUSPEND.
+ *
+ *     This mechanism is DEPRECATED and should only be used for testing.
  */
 
 static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
@@ -38,6 +45,10 @@ static ssize_t state_store(struct device * dev, struct device_attribute *attr, c
        pm_message_t state;
        int error = -EINVAL;
 
+       /* disallow incomplete suspend sequences */
+       if (dev->bus && (dev->bus->suspend_late || dev->bus->resume_early))
+               return error;
+
        state.event = PM_EVENT_SUSPEND;
        /* Older apps expected to write "3" here - confused with PCI D3 */
        if ((n == 1) && !strcmp(buf, "3"))
@@ -57,6 +68,8 @@ static ssize_t state_store(struct device * dev, struct device_attribute *attr, c
 static DEVICE_ATTR(state, 0644, state_show, state_store);
 
 
+#endif /* CONFIG_PM_SYSFS_DEPRECATED */
+
 /*
  *     wakeup - Report/change current wakeup option for device
  *
@@ -130,7 +143,9 @@ static DEVICE_ATTR(wakeup, 0644, wake_show, wake_store);
 
 
 static struct attribute * power_attrs[] = {
+#ifdef CONFIG_PM_SYSFS_DEPRECATED
        &dev_attr_state.attr,
+#endif
        &dev_attr_wakeup.attr,
        NULL,
 };
index 7b3b94ddddccb4aaf5cab64e6e94923ab2fb6c49..c774121684d7f8951ff8b0acafef0e74ce11e23d 100644 (file)
@@ -662,7 +662,8 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
 
        mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
        lo->lo_backing_file = file;
-       lo->lo_blocksize = mapping->host->i_blksize;
+       lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ?
+               mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
        lo->old_gfp_mask = mapping_gfp_mask(mapping);
        mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
        complete(&p->wait);
@@ -794,7 +795,9 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
                if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
                        lo_flags |= LO_FLAGS_READ_ONLY;
 
-               lo_blocksize = inode->i_blksize;
+               lo_blocksize = S_ISBLK(inode->i_mode) ?
+                       inode->i_bdev->bd_block_size : PAGE_SIZE;
+
                error = 0;
        } else {
                goto out_putf;
index d62b49fbf10c319334ca6f26e49f58a46747b6f3..45a8f402b07bd6c214ce69a1a3b348c32127cda8 100644 (file)
@@ -358,7 +358,7 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
 static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_scsi_cmd *cmd, struct ub_request *urq);
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_end_rq(struct request *rq, int uptodate);
+static void ub_end_rq(struct request *rq, unsigned int status);
 static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
     struct ub_request *urq, struct ub_scsi_cmd *cmd);
 static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -639,9 +639,15 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
        struct ub_request *urq;
        int n_elem;
 
-       if (atomic_read(&sc->poison) || lun->changed) {
+       if (atomic_read(&sc->poison)) {
+               blkdev_dequeue_request(rq);
+               ub_end_rq(rq, DID_NO_CONNECT << 16);
+               return 0;
+       }
+
+       if (lun->changed && !blk_pc_request(rq)) {
                blkdev_dequeue_request(rq);
-               ub_end_rq(rq, 0);
+               ub_end_rq(rq, SAM_STAT_CHECK_CONDITION);
                return 0;
        }
 
@@ -693,7 +699,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
 
 drop:
        ub_put_cmd(lun, cmd);
-       ub_end_rq(rq, 0);
+       ub_end_rq(rq, DID_ERROR << 16);
        return 0;
 }
 
@@ -761,47 +767,53 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        struct ub_lun *lun = cmd->lun;
        struct ub_request *urq = cmd->back;
        struct request *rq;
-       int uptodate;
+       unsigned int scsi_status;
 
        rq = urq->rq;
 
        if (cmd->error == 0) {
-               uptodate = 1;
-
                if (blk_pc_request(rq)) {
                        if (cmd->act_len >= rq->data_len)
                                rq->data_len = 0;
                        else
                                rq->data_len -= cmd->act_len;
                }
+               scsi_status = 0;
        } else {
-               uptodate = 0;
-
                if (blk_pc_request(rq)) {
                        /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
                        memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
                        rq->sense_len = UB_SENSE_SIZE;
                        if (sc->top_sense[0] != 0)
-                               rq->errors = SAM_STAT_CHECK_CONDITION;
+                               scsi_status = SAM_STAT_CHECK_CONDITION;
                        else
-                               rq->errors = DID_ERROR << 16;
+                               scsi_status = DID_ERROR << 16;
                } else {
                        if (cmd->error == -EIO) {
                                if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
                                        return;
                        }
+                       scsi_status = SAM_STAT_CHECK_CONDITION;
                }
        }
 
        urq->rq = NULL;
 
        ub_put_cmd(lun, cmd);
-       ub_end_rq(rq, uptodate);
+       ub_end_rq(rq, scsi_status);
        blk_start_queue(lun->disk->queue);
 }
 
-static void ub_end_rq(struct request *rq, int uptodate)
+static void ub_end_rq(struct request *rq, unsigned int scsi_status)
 {
+       int uptodate;
+
+       if (scsi_status == 0) {
+               uptodate = 1;
+       } else {
+               uptodate = 0;
+               rq->errors = scsi_status;
+       }
        end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
        end_that_request_last(rq, uptodate);
 }
index 52ea94b891f59cedb6a8d50794240d43c37598d6..1b21c3a911d954f571634e05fc6b6be2815f1592 100644 (file)
@@ -439,6 +439,14 @@ config SGI_MBCS
          If you have an SGI Altix with an attached SABrick
          say Y or M here, otherwise say N.
 
+config MSPEC
+       tristate "Memory special operations driver"
+       depends on IA64
+       help
+         If you have an ia64 and you want to enable memory special
+         operations support (formerly known as fetchop), say Y here,
+         otherwise say N.
+
 source "drivers/serial/Kconfig"
 
 config UNIX98_PTYS
@@ -739,7 +747,7 @@ config NVRAM
 
 config RTC
        tristate "Enhanced Real Time Clock Support"
-       depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM
+       depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH
        ---help---
          If you say Y here and create a character special file /dev/rtc with
          major number 10 and minor number 135 using mknod ("man mknod"), you
index 8c6dfc6215201d238ab629847a7fd173bb543536..b583d0cd9fbe207b00fc97abca82a2ecd15fa70f 100644 (file)
@@ -47,6 +47,7 @@ obj-$(CONFIG_HVC_RTAS)                += hvc_rtas.o
 obj-$(CONFIG_HVC_DRIVER)       += hvc_console.o
 obj-$(CONFIG_RAW_DRIVER)       += raw.o
 obj-$(CONFIG_SGI_SNSC)         += snsc.o snsc_event.o
+obj-$(CONFIG_MSPEC)            += mspec.o
 obj-$(CONFIG_MMTIMER)          += mmtimer.o
 obj-$(CONFIG_VIOCONS)          += viocons.o
 obj-$(CONFIG_VIOTAPE)          += viotape.o
index 8afba339f05ab3bca332c939db69845e39293824..58b0eb58111457713088be8daaffb2a9cac44d89 100644 (file)
@@ -868,8 +868,8 @@ int hpet_alloc(struct hpet_data *hdp)
        do_div(temp, period);
        hpetp->hp_tick_freq = temp; /* ticks per second */
 
-       printk(KERN_INFO "hpet%d: at MMIO 0x%lx (virtual 0x%p), IRQ%s",
-               hpetp->hp_which, hdp->hd_phys_address, hdp->hd_address,
+       printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s",
+               hpetp->hp_which, hdp->hd_phys_address,
                hpetp->hp_ntimer > 1 ? "s" : "");
        for (i = 0; i < hpetp->hp_ntimer; i++)
                printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
index 917b20402664aad5ccf970255f65f15974f06eab..4ac70ec697f07f7b6b15c52d231709b7dd64577b 100644 (file)
@@ -238,6 +238,32 @@ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
 }
 #endif
 
+#ifndef CONFIG_MMU
+static unsigned long get_unmapped_area_mem(struct file *file,
+                                          unsigned long addr,
+                                          unsigned long len,
+                                          unsigned long pgoff,
+                                          unsigned long flags)
+{
+       if (!valid_mmap_phys_addr_range(pgoff, len))
+               return (unsigned long) -EINVAL;
+       return pgoff;
+}
+
+/* can't do an in-place private mapping if there's no MMU */
+static inline int private_mapping_ok(struct vm_area_struct *vma)
+{
+       return vma->vm_flags & VM_MAYSHARE;
+}
+#else
+#define get_unmapped_area_mem  NULL
+
+static inline int private_mapping_ok(struct vm_area_struct *vma)
+{
+       return 1;
+}
+#endif
+
 static int mmap_mem(struct file * file, struct vm_area_struct * vma)
 {
        size_t size = vma->vm_end - vma->vm_start;
@@ -245,6 +271,9 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
        if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
                return -EINVAL;
 
+       if (!private_mapping_ok(vma))
+               return -ENOSYS;
+
        vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff,
                                                 size,
                                                 vma->vm_page_prot);
@@ -782,6 +811,7 @@ static const struct file_operations mem_fops = {
        .write          = write_mem,
        .mmap           = mmap_mem,
        .open           = open_mem,
+       .get_unmapped_area = get_unmapped_area_mem,
 };
 
 static const struct file_operations kmem_fops = {
@@ -790,6 +820,7 @@ static const struct file_operations kmem_fops = {
        .write          = write_kmem,
        .mmap           = mmap_kmem,
        .open           = open_kmem,
+       .get_unmapped_area = get_unmapped_area_mem,
 };
 
 static const struct file_operations null_fops = {
@@ -815,6 +846,10 @@ static const struct file_operations zero_fops = {
        .mmap           = mmap_zero,
 };
 
+/*
+ * capabilities for /dev/zero
+ * - permits private mappings, "copies" are taken of the source of zeros
+ */
 static struct backing_dev_info zero_bdi = {
        .capabilities   = BDI_CAP_MAP_COPY,
 };
@@ -862,9 +897,13 @@ static int memory_open(struct inode * inode, struct file * filp)
        switch (iminor(inode)) {
                case 1:
                        filp->f_op = &mem_fops;
+                       filp->f_mapping->backing_dev_info =
+                               &directly_mappable_cdev_bdi;
                        break;
                case 2:
                        filp->f_op = &kmem_fops;
+                       filp->f_mapping->backing_dev_info =
+                               &directly_mappable_cdev_bdi;
                        break;
                case 3:
                        filp->f_op = &null_fops;
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
new file mode 100644 (file)
index 0000000..5426b1e
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2001-2006 Silicon Graphics, Inc.  All rights
+ * reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+/*
+ * SN Platform Special Memory (mspec) Support
+ *
+ * This driver exports the SN special memory (mspec) facility to user
+ * processes.
+ * There are three types of memory made available thru this driver:
+ * fetchops, uncached and cached.
+ *
+ * Fetchops are atomic memory operations that are implemented in the
+ * memory controller on SGI SN hardware.
+ *
+ * Uncached are used for memory write combining feature of the ia64
+ * cpu.
+ *
+ * Cached are used for areas of memory that are used as cached addresses
+ * on our partition and used as uncached addresses from other partitions.
+ * Due to a design constraint of the SN2 Shub, you can not have processors
+ * on the same FSB perform both a cached and uncached reference to the
+ * same cache line.  These special memory cached regions prevent the
+ * kernel from ever dropping in a TLB entry and therefore prevent the
+ * processor from ever speculating a cache line from this page.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/numa.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/atomic.h>
+#include <asm/tlbflush.h>
+#include <asm/uncached.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/mspec.h>
+#include <asm/sn/sn_cpuid.h>
+#include <asm/sn/io.h>
+#include <asm/sn/bte.h>
+#include <asm/sn/shubio.h>
+
+
+#define FETCHOP_ID     "SGI Fetchop,"
+#define CACHED_ID      "Cached,"
+#define UNCACHED_ID    "Uncached"
+#define REVISION       "4.0"
+#define MSPEC_BASENAME "mspec"
+
+/*
+ * Page types allocated by the device.
+ */
+enum {
+       MSPEC_FETCHOP = 1,
+       MSPEC_CACHED,
+       MSPEC_UNCACHED
+};
+
+static int is_sn2;
+
+/*
+ * One of these structures is allocated when an mspec region is mmaped. The
+ * structure is pointed to by the vma->vm_private_data field in the vma struct.
+ * This structure is used to record the addresses of the mspec pages.
+ */
+struct vma_data {
+       atomic_t refcnt;        /* Number of vmas sharing the data. */
+       spinlock_t lock;        /* Serialize access to the vma. */
+       int count;              /* Number of pages allocated. */
+       int type;               /* Type of pages allocated. */
+       unsigned long maddr[0]; /* Array of MSPEC addresses. */
+};
+
+/* used on shub2 to clear FOP cache in the HUB */
+static unsigned long scratch_page[MAX_NUMNODES];
+#define SH2_AMO_CACHE_ENTRIES  4
+
+static inline int
+mspec_zero_block(unsigned long addr, int len)
+{
+       int status;
+
+       if (is_sn2) {
+               if (is_shub2()) {
+                       int nid;
+                       void *p;
+                       int i;
+
+                       nid = nasid_to_cnodeid(get_node_number(__pa(addr)));
+                       p = (void *)TO_AMO(scratch_page[nid]);
+
+                       for (i=0; i < SH2_AMO_CACHE_ENTRIES; i++) {
+                               FETCHOP_LOAD_OP(p, FETCHOP_LOAD);
+                               p += FETCHOP_VAR_SIZE;
+                       }
+               }
+
+               status = bte_copy(0, addr & ~__IA64_UNCACHED_OFFSET, len,
+                                 BTE_WACQUIRE | BTE_ZERO_FILL, NULL);
+       } else {
+               memset((char *) addr, 0, len);
+               status = 0;
+       }
+       return status;
+}
+
+/*
+ * mspec_open
+ *
+ * Called when a device mapping is created by a means other than mmap
+ * (via fork, etc.).  Increments the reference count on the underlying
+ * mspec data so it is not freed prematurely.
+ */
+static void
+mspec_open(struct vm_area_struct *vma)
+{
+       struct vma_data *vdata;
+
+       vdata = vma->vm_private_data;
+       atomic_inc(&vdata->refcnt);
+}
+
+/*
+ * mspec_close
+ *
+ * Called when unmapping a device mapping. Frees all mspec pages
+ * belonging to the vma.
+ */
+static void
+mspec_close(struct vm_area_struct *vma)
+{
+       struct vma_data *vdata;
+       int i, pages, result, vdata_size;
+
+       vdata = vma->vm_private_data;
+       if (!atomic_dec_and_test(&vdata->refcnt))
+               return;
+
+       pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
+       for (i = 0; i < pages; i++) {
+               if (vdata->maddr[i] == 0)
+                       continue;
+               /*
+                * Clear the page before sticking it back
+                * into the pool.
+                */
+               result = mspec_zero_block(vdata->maddr[i], PAGE_SIZE);
+               if (!result)
+                       uncached_free_page(vdata->maddr[i]);
+               else
+                       printk(KERN_WARNING "mspec_close(): "
+                              "failed to zero page %i\n",
+                              result);
+       }
+
+       if (vdata_size <= PAGE_SIZE)
+               kfree(vdata);
+       else
+               vfree(vdata);
+}
+
+
+/*
+ * mspec_nopfn
+ *
+ * Creates a mspec page and maps it to user space.
+ */
+static unsigned long
+mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
+{
+       unsigned long paddr, maddr;
+       unsigned long pfn;
+       int index;
+       struct vma_data *vdata = vma->vm_private_data;
+
+       index = (address - vma->vm_start) >> PAGE_SHIFT;
+       maddr = (volatile unsigned long) vdata->maddr[index];
+       if (maddr == 0) {
+               maddr = uncached_alloc_page(numa_node_id());
+               if (maddr == 0)
+                       return NOPFN_OOM;
+
+               spin_lock(&vdata->lock);
+               if (vdata->maddr[index] == 0) {
+                       vdata->count++;
+                       vdata->maddr[index] = maddr;
+               } else {
+                       uncached_free_page(maddr);
+                       maddr = vdata->maddr[index];
+               }
+               spin_unlock(&vdata->lock);
+       }
+
+       if (vdata->type == MSPEC_FETCHOP)
+               paddr = TO_AMO(maddr);
+       else
+               paddr = __pa(TO_CAC(maddr));
+
+       pfn = paddr >> PAGE_SHIFT;
+
+       return pfn;
+}
+
+static struct vm_operations_struct mspec_vm_ops = {
+       .open = mspec_open,
+       .close = mspec_close,
+       .nopfn = mspec_nopfn
+};
+
+/*
+ * mspec_mmap
+ *
+ * Called when mmaping the device.  Initializes the vma with a fault handler
+ * and private data structure necessary to allocate, track, and free the
+ * underlying pages.
+ */
+static int
+mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
+{
+       struct vma_data *vdata;
+       int pages, vdata_size;
+
+       if (vma->vm_pgoff != 0)
+               return -EINVAL;
+
+       if ((vma->vm_flags & VM_SHARED) == 0)
+               return -EINVAL;
+
+       if ((vma->vm_flags & VM_WRITE) == 0)
+               return -EPERM;
+
+       pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+       vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
+       if (vdata_size <= PAGE_SIZE)
+               vdata = kmalloc(vdata_size, GFP_KERNEL);
+       else
+               vdata = vmalloc(vdata_size);
+       if (!vdata)
+               return -ENOMEM;
+       memset(vdata, 0, vdata_size);
+
+       vdata->type = type;
+       spin_lock_init(&vdata->lock);
+       vdata->refcnt = ATOMIC_INIT(1);
+       vma->vm_private_data = vdata;
+
+       vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED | VM_PFNMAP);
+       if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED)
+               vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+       vma->vm_ops = &mspec_vm_ops;
+
+       return 0;
+}
+
+static int
+fetchop_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       return mspec_mmap(file, vma, MSPEC_FETCHOP);
+}
+
+static int
+cached_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       return mspec_mmap(file, vma, MSPEC_CACHED);
+}
+
+static int
+uncached_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       return mspec_mmap(file, vma, MSPEC_UNCACHED);
+}
+
+static struct file_operations fetchop_fops = {
+       .owner = THIS_MODULE,
+       .mmap = fetchop_mmap
+};
+
+static struct miscdevice fetchop_miscdev = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "sgi_fetchop",
+       .fops = &fetchop_fops
+};
+
+static struct file_operations cached_fops = {
+       .owner = THIS_MODULE,
+       .mmap = cached_mmap
+};
+
+static struct miscdevice cached_miscdev = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "mspec_cached",
+       .fops = &cached_fops
+};
+
+static struct file_operations uncached_fops = {
+       .owner = THIS_MODULE,
+       .mmap = uncached_mmap
+};
+
+static struct miscdevice uncached_miscdev = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = "mspec_uncached",
+       .fops = &uncached_fops
+};
+
+/*
+ * mspec_init
+ *
+ * Called at boot time to initialize the mspec facility.
+ */
+static int __init
+mspec_init(void)
+{
+       int ret;
+       int nid;
+
+       /*
+        * The fetchop device only works on SN2 hardware, uncached and cached
+        * memory drivers should both be valid on all ia64 hardware
+        */
+       if (ia64_platform_is("sn2")) {
+               is_sn2 = 1;
+               if (is_shub2()) {
+                       ret = -ENOMEM;
+                       for_each_online_node(nid) {
+                               int actual_nid;
+                               int nasid;
+                               unsigned long phys;
+
+                               scratch_page[nid] = uncached_alloc_page(nid);
+                               if (scratch_page[nid] == 0)
+                                       goto free_scratch_pages;
+                               phys = __pa(scratch_page[nid]);
+                               nasid = get_node_number(phys);
+                               actual_nid = nasid_to_cnodeid(nasid);
+                               if (actual_nid != nid)
+                                       goto free_scratch_pages;
+                       }
+               }
+
+               ret = misc_register(&fetchop_miscdev);
+               if (ret) {
+                       printk(KERN_ERR
+                              "%s: failed to register device %i\n",
+                              FETCHOP_ID, ret);
+                       goto free_scratch_pages;
+               }
+       }
+       ret = misc_register(&cached_miscdev);
+       if (ret) {
+               printk(KERN_ERR "%s: failed to register device %i\n",
+                      CACHED_ID, ret);
+               if (is_sn2)
+                       misc_deregister(&fetchop_miscdev);
+               goto free_scratch_pages;
+       }
+       ret = misc_register(&uncached_miscdev);
+       if (ret) {
+               printk(KERN_ERR "%s: failed to register device %i\n",
+                      UNCACHED_ID, ret);
+               misc_deregister(&cached_miscdev);
+               if (is_sn2)
+                       misc_deregister(&fetchop_miscdev);
+               goto free_scratch_pages;
+       }
+
+       printk(KERN_INFO "%s %s initialized devices: %s %s %s\n",
+              MSPEC_BASENAME, REVISION, is_sn2 ? FETCHOP_ID : "",
+              CACHED_ID, UNCACHED_ID);
+
+       return 0;
+
+ free_scratch_pages:
+       for_each_node(nid) {
+               if (scratch_page[nid] != 0)
+                       uncached_free_page(scratch_page[nid]);
+       }
+       return ret;
+}
+
+static void __exit
+mspec_exit(void)
+{
+       int nid;
+
+       misc_deregister(&uncached_miscdev);
+       misc_deregister(&cached_miscdev);
+       if (is_sn2) {
+               misc_deregister(&fetchop_miscdev);
+
+               for_each_node(nid) {
+                       if (scratch_page[nid] != 0)
+                               uncached_free_page(scratch_page[nid]);
+               }
+       }
+}
+
+module_init(mspec_init);
+module_exit(mspec_exit);
+
+MODULE_AUTHOR("Silicon Graphics, Inc. <linux-altix@sgi.com>");
+MODULE_DESCRIPTION("Driver for SGI SN special memory operations");
+MODULE_LICENSE("GPL");
index fff89c2d88fda66ad93bb40e822137b2751477b5..f114d7b5bb2a0f195933cb377099c09fa4becb83 100644 (file)
@@ -510,6 +510,14 @@ config SH_WDT
          To compile this driver as a module, choose M here: the
          module will be called shwdt.
 
+config SH_WDT_MMAP
+       bool "Allow mmap of SH WDT"
+       default n
+       depends on SH_WDT
+       help
+         If you say Y here, user applications will be able to mmap the
+         WDT/CPG registers.
+#
 # SPARC64 Architecture
 
 config WATCHDOG_CP1XXX
index 1355038f10440e27f4a708eea95694f897edbc0a..e5b8c64f1d65acf4ac67dfb8f77d5376d2ac974e 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/notifier.h>
 #include <linux/ioport.h>
 #include <linux/fs.h>
-
+#include <linux/mm.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/watchdog.h>
@@ -125,7 +125,6 @@ static void sh_wdt_start(void)
 
 /**
  *     sh_wdt_stop - Stop the Watchdog
- *
  *     Stops the watchdog.
  */
 static void sh_wdt_stop(void)
@@ -141,22 +140,20 @@ static void sh_wdt_stop(void)
 
 /**
  *     sh_wdt_keepalive - Keep the Userspace Watchdog Alive
- *
  *     The Userspace watchdog got a KeepAlive: schedule the next heartbeat.
  */
-static void sh_wdt_keepalive(void)
+static inline void sh_wdt_keepalive(void)
 {
        next_heartbeat = jiffies + (heartbeat * HZ);
 }
 
 /**
  *     sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat
- *
  *     Set the Userspace Watchdog heartbeat
  */
 static int sh_wdt_set_heartbeat(int t)
 {
-       if ((t < 1) || (t > 3600)) /* arbitrary upper limit */
+       if (unlikely((t < 1) || (t > 3600))) /* arbitrary upper limit */
                return -EINVAL;
 
        heartbeat = t;
@@ -165,7 +162,6 @@ static int sh_wdt_set_heartbeat(int t)
 
 /**
  *     sh_wdt_ping - Ping the Watchdog
- *
  *     @data: Unused
  *
  *     Clears overflow bit, resets timer counter.
@@ -182,14 +178,13 @@ static void sh_wdt_ping(unsigned long data)
                sh_wdt_write_cnt(0);
 
                mod_timer(&timer, next_ping_period(clock_division_ratio));
-       } else {
-               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
-       }
+       } else
+               printk(KERN_WARNING PFX "Heartbeat lost! Will not ping "
+                      "the watchdog\n");
 }
 
 /**
  *     sh_wdt_open - Open the Device
- *
  *     @inode: inode of device
  *     @file: file handle of device
  *
@@ -209,7 +204,6 @@ static int sh_wdt_open(struct inode *inode, struct file *file)
 
 /**
  *     sh_wdt_close - Close the Device
- *
  *     @inode: inode of device
  *     @file: file handle of device
  *
@@ -220,7 +214,8 @@ static int sh_wdt_close(struct inode *inode, struct file *file)
        if (shwdt_expect_close == 42) {
                sh_wdt_stop();
        } else {
-               printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+               printk(KERN_CRIT PFX "Unexpected close, not "
+                      "stopping watchdog!\n");
                sh_wdt_keepalive();
        }
 
@@ -232,7 +227,6 @@ static int sh_wdt_close(struct inode *inode, struct file *file)
 
 /**
  *     sh_wdt_write - Write to Device
- *
  *     @file: file handle of device
  *     @buf: buffer to write
  *     @count: length of buffer
@@ -264,8 +258,56 @@ static ssize_t sh_wdt_write(struct file *file, const char *buf,
 }
 
 /**
- *     sh_wdt_ioctl - Query Device
+ *     sh_wdt_mmap - map WDT/CPG registers into userspace
+ *     @file: file structure for the device
+ *     @vma: VMA to map the registers into
+ *
+ *     A simple mmap() implementation for the corner cases where the counter
+ *     needs to be mapped in userspace directly. Due to the relatively small
+ *     size of the area, neighbouring registers not necessarily tied to the
+ *     CPG will also be accessible through the register page, so this remains
+ *     configurable for users that really know what they're doing.
  *
+ *     Additionaly, the register page maps in the CPG register base relative
+ *     to the nearest page-aligned boundary, which requires that userspace do
+ *     the appropriate CPU subtype math for calculating the page offset for
+ *     the counter value.
+ */
+static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       int ret = -ENOSYS;
+
+#ifdef CONFIG_SH_WDT_MMAP
+       unsigned long addr;
+
+       /* Only support the simple cases where we map in a register page. */
+       if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
+               return -EINVAL;
+
+       /*
+        * Pick WTCNT as the start, it's usually the first register after the
+        * FRQCR, and neither one are generally page-aligned out of the box.
+        */
+       addr = WTCNT & ~(PAGE_SIZE - 1);
+
+       vma->vm_flags |= VM_IO;
+       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+       if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
+                              PAGE_SIZE, vma->vm_page_prot)) {
+               printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
+                      __FUNCTION__);
+               return -EAGAIN;
+       }
+
+       ret = 0;
+#endif
+
+       return ret;
+}
+
+/**
+ *     sh_wdt_ioctl - Query Device
  *     @inode: inode of device
  *     @file: file handle of device
  *     @cmd: watchdog command
@@ -326,7 +368,6 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file,
 
 /**
  *     sh_wdt_notify_sys - Notifier Handler
- *
  *     @this: notifier block
  *     @code: notifier event
  *     @unused: unused
@@ -337,9 +378,8 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file,
 static int sh_wdt_notify_sys(struct notifier_block *this,
                             unsigned long code, void *unused)
 {
-       if (code == SYS_DOWN || code == SYS_HALT) {
+       if (code == SYS_DOWN || code == SYS_HALT)
                sh_wdt_stop();
-       }
 
        return NOTIFY_DONE;
 }
@@ -351,10 +391,12 @@ static const struct file_operations sh_wdt_fops = {
        .ioctl          = sh_wdt_ioctl,
        .open           = sh_wdt_open,
        .release        = sh_wdt_close,
+       .mmap           = sh_wdt_mmap,
 };
 
 static struct watchdog_info sh_wdt_info = {
-       .options                = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+       .options                = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
+                                 WDIOF_MAGICCLOSE,
        .firmware_version       = 1,
        .identity               = "SH WDT",
 };
@@ -371,7 +413,6 @@ static struct miscdevice sh_wdt_miscdev = {
 
 /**
  *     sh_wdt_init - Initialize module
- *
  *     Registers the device and notifier handler. Actual device
  *     initialization is handled by sh_wdt_open().
  */
@@ -381,15 +422,15 @@ static int __init sh_wdt_init(void)
 
        if ((clock_division_ratio < 0x5) || (clock_division_ratio > 0x7)) {
                clock_division_ratio = WTCSR_CKS_4096;
-               printk(KERN_INFO PFX "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n",
-                       clock_division_ratio);
+               printk(KERN_INFO PFX "clock_division_ratio value must "
+                      "be 0x5<=x<=0x7, using %d\n", clock_division_ratio);
        }
 
-       if (sh_wdt_set_heartbeat(heartbeat))
-       {
+       rc = sh_wdt_set_heartbeat(heartbeat);
+       if (unlikely(rc)) {
                heartbeat = WATCHDOG_HEARTBEAT;
-               printk(KERN_INFO PFX "heartbeat value must be 1<=x<=3600, using %d\n",
-                       heartbeat);
+               printk(KERN_INFO PFX "heartbeat value must "
+                      "be 1<=x<=3600, using %d\n", heartbeat);
        }
 
        init_timer(&timer);
@@ -397,15 +438,16 @@ static int __init sh_wdt_init(void)
        timer.data = 0;
 
        rc = register_reboot_notifier(&sh_wdt_notifier);
-       if (rc) {
-               printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n", rc);
+       if (unlikely(rc)) {
+               printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n",
+                      rc);
                return rc;
        }
 
        rc = misc_register(&sh_wdt_miscdev);
-       if (rc) {
-               printk(KERN_ERR PFX "Can't register miscdev on minor=%d (err=%d)\n",
-                       sh_wdt_miscdev.minor, rc);
+       if (unlikely(rc)) {
+               printk(KERN_ERR PFX "Can't register miscdev on "
+                      "minor=%d (err=%d)\n", sh_wdt_miscdev.minor, rc);
                unregister_reboot_notifier(&sh_wdt_notifier);
                return rc;
        }
@@ -418,7 +460,6 @@ static int __init sh_wdt_init(void)
 
 /**
  *     sh_wdt_exit - Deinitialize module
- *
  *     Unregisters the device and notifier handler. Actual device
  *     deinitialization is handled by sh_wdt_close().
  */
@@ -434,14 +475,13 @@ MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 
 module_param(clock_division_ratio, int, 0);
-MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7.");
+MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")");
 
 module_param(heartbeat, int, 0);
 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<=heartbeat<=3600, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
 
 module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
 module_init(sh_wdt_init);
 module_exit(sh_wdt_exit);
-
index 6078e2f588172e73aad9ad45ec2a3cfb9eb7e97d..3a365e159d89d52df59b945d22bb7bd1408022f9 100644 (file)
@@ -128,9 +128,23 @@ static int eisa_bus_match (struct device *dev, struct device_driver *drv)
        return 0;
 }
 
+static int eisa_bus_uevent(struct device *dev, char **envp, int num_envp,
+                          char *buffer, int buffer_size)
+{
+       struct eisa_device *edev = to_eisa_device(dev);
+       int i = 0;
+       int length = 0;
+
+       add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length,
+                      "MODALIAS=" EISA_DEVICE_MODALIAS_FMT, edev->id.sig);
+       envp[i] = NULL;
+       return 0;
+}
+
 struct bus_type eisa_bus_type = {
        .name  = "eisa",
        .match = eisa_bus_match,
+       .uevent = eisa_bus_uevent,
 };
 
 int eisa_driver_register (struct eisa_driver *edrv)
@@ -160,6 +174,14 @@ static ssize_t eisa_show_state (struct device *dev, struct device_attribute *att
 
 static DEVICE_ATTR(enabled, S_IRUGO, eisa_show_state, NULL);
 
+static ssize_t eisa_show_modalias (struct device *dev, struct device_attribute *attr, char *buf)
+{
+        struct eisa_device *edev = to_eisa_device (dev);
+        return sprintf (buf, EISA_DEVICE_MODALIAS_FMT "\n", edev->id.sig);
+}
+
+static DEVICE_ATTR(modalias, S_IRUGO, eisa_show_modalias, NULL);
+
 static int __init eisa_init_device (struct eisa_root_device *root,
                                    struct eisa_device *edev,
                                    int slot)
@@ -209,6 +231,7 @@ static int __init eisa_register_device (struct eisa_device *edev)
 
        device_create_file (&edev->dev, &dev_attr_signature);
        device_create_file (&edev->dev, &dev_attr_enabled);
+       device_create_file (&edev->dev, &dev_attr_modalias);
 
        return 0;
 }
index 06df92b3ee492ccbfe3db607e1bd221e65a48b87..b0ee57492228bc42f8d3154378249978b713cffa 100644 (file)
@@ -243,6 +243,7 @@ static struct i2c_driver it87_driver = {
 
 static struct i2c_driver it87_isa_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "it87-isa",
        },
        .attach_adapter = it87_isa_attach_adapter,
index a6ce7abf86025dda21531ac6ecddd611926b705e..fa1715b9a9967618a398006bc73ea9a4f6b316f4 100644 (file)
@@ -175,6 +175,7 @@ static struct i2c_driver lm78_driver = {
 
 static struct i2c_driver lm78_isa_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "lm78-isa",
        },
        .attach_adapter = lm78_isa_attach_adapter,
index ae05e483a77877673ea47825960d955e4c2162c7..236f9f29c624647dcea8e4eb9518be488cabcce7 100644 (file)
@@ -238,6 +238,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev);
 
 static struct i2c_driver pc87360_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "pc87360",
        },
        .attach_adapter = pc87360_detect,
index 063f71c5f07eabf14f33dc671e2b1da6df73eedf..3783af4195bd9452e758ac84e874fe132e4d1767 100644 (file)
@@ -200,6 +200,7 @@ static void sis5595_init_client(struct i2c_client *client);
 
 static struct i2c_driver sis5595_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "sis5595",
        },
        .attach_adapter = sis5595_detect,
index b6086186d2259dea1f7235beb246f6b9c5f2672d..a85869393bab323f361a94b3daee02fb46bb599f 100644 (file)
@@ -228,6 +228,7 @@ static int smsc47b397_detect(struct i2c_adapter *adapter);
 
 static struct i2c_driver smsc47b397_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "smsc47b397",
        },
        .attach_adapter = smsc47b397_detect,
index 825e8f72698fdf8d24bf021e88d7551f167749bb..6c81b843d8314b9ef6ee9a4df0003d7fbaa93ad4 100644 (file)
@@ -128,6 +128,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
 
 static struct i2c_driver smsc47m1_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "smsc47m1",
        },
        .attach_adapter = smsc47m1_detect,
index 166298f1f19023dc349feda1a62f78d104132420..95ae056e5a94a8a8729ddc223ec771b6cb09fb73 100644 (file)
@@ -574,6 +574,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
    smbus_driver and isa_driver, and clients could be of either kind */
 static struct i2c_driver via686a_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "via686a",
        },
        .attach_adapter = via686a_detect,
index 686f3deb3093844f4129a338b8e441052225b344..236ccf0e915d70917b248a9f67f23e227fe44e1a 100644 (file)
@@ -587,6 +587,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 static struct i2c_driver vt8231_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "vt8231",
        },
        .attach_adapter = vt8231_detect,
index 40301bc6ce186e5a1c92c7a7d9964e945807dac7..b21d6b9d7eac730ede45e89fbd67b871cddcb30d 100644 (file)
@@ -903,6 +903,7 @@ static int w83627ehf_detach_client(struct i2c_client *client)
 
 static struct i2c_driver w83627ehf_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "w83627ehf",
        },
        .attach_adapter = w83627ehf_detect,
index 79368d53c3634645a4a72b9425dd142df9fc4817..30295028ea99238ea89e0d59b40fa580018c5cc6 100644 (file)
@@ -339,6 +339,7 @@ static void w83627hf_init_client(struct i2c_client *client);
 
 static struct i2c_driver w83627hf_driver = {
        .driver = {
+               .owner  = THIS_MODULE,
                .name   = "w83627hf",
        },
        .attach_adapter = w83627hf_detect,
index 7be469ed0f8f4a41cc30c6ecd48eaf09210fafa8..95221b14e13a511749982ae13071932cda5fbe27 100644 (file)
@@ -288,6 +288,7 @@ static struct i2c_driver w83781d_driver = {
 
 static struct i2c_driver w83781d_isa_driver = {
        .driver = {
+               .owner = THIS_MODULE,
                .name = "w83781d-isa",
        },
        .attach_adapter = w83781d_isa_attach_adapter,
index 24383afdda76d4c446445381b91482e0a9938f2b..11935f66fcd8fcf839bafc73c74fbb1eb1a9f009 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Character device configuration
+# I2C subsystem configuration
 #
 
 menu "I2C support"
index 30408015d231fa485157020b477f4ee892389eef..c034820615bb7ff8bdea1d161f3590b3cd6685a7 100644 (file)
@@ -53,12 +53,6 @@ config I2C_ALGO8XX
        tristate "MPC8xx CPM I2C interface"
        depends on 8xx && I2C
 
-config I2C_ALGO_SIBYTE
-       tristate "SiByte SMBus interface"
-       depends on SIBYTE_SB1xxx_SOC && I2C
-       help
-         Supports the SiByte SOC on-chip I2C interfaces (2 channels).
-
 config I2C_ALGO_SGI
        tristate "I2C SGI interfaces"
        depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS)
index 867fe1f67401c31f3cfabfa598894cdc59d8d70e..208be04a3dbdc6eb097e57a23ad4a4e7bc0d60ed 100644 (file)
@@ -6,7 +6,6 @@ obj-$(CONFIG_I2C_ALGOBIT)       += i2c-algo-bit.o
 obj-$(CONFIG_I2C_ALGOPCF)      += i2c-algo-pcf.o
 obj-$(CONFIG_I2C_ALGOPCA)      += i2c-algo-pca.o
 obj-$(CONFIG_I2C_ALGOITE)      += i2c-algo-ite.o
-obj-$(CONFIG_I2C_ALGO_SIBYTE)  += i2c-algo-sibyte.o
 obj-$(CONFIG_I2C_ALGO_SGI)     += i2c-algo-sgi.o
 
 ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
index ab230c033f9930ce293cf7ae1057db559f60b80e..21c36bfb5e6bf1b25522e7492bef978e29a8bde0 100644 (file)
@@ -76,17 +76,15 @@ static inline void scllo(struct i2c_algo_bit_data *adap)
  * Raise scl line, and do checking for delays. This is necessary for slower
  * devices.
  */
-static inline int sclhi(struct i2c_algo_bit_data *adap)
+static int sclhi(struct i2c_algo_bit_data *adap)
 {
        unsigned long start;
 
        setscl(adap,1);
 
        /* Not all adapters have scl sense line... */
-       if (adap->getscl == NULL ) {
-               udelay(adap->udelay);
-               return 0;
-       }
+       if (!adap->getscl)
+               goto done;
 
        start=jiffies;
        while (! getscl(adap) ) {       
@@ -101,6 +99,8 @@ static inline int sclhi(struct i2c_algo_bit_data *adap)
                cond_resched();
        }
        DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start));
+
+done:
        udelay(adap->udelay);
        return 0;
 } 
@@ -121,7 +121,6 @@ static void i2c_repstart(struct i2c_algo_bit_data *adap)
        DEBPROTO(printk(" Sr "));
        setsda(adap,1);
        sclhi(adap);
-       udelay(adap->udelay);
        
        sdalo(adap);
        scllo(adap);
@@ -306,7 +305,7 @@ bailout:
  * 0 chip did not answer
  * -x transmission error
  */
-static inline int try_address(struct i2c_adapter *i2c_adap,
+static int try_address(struct i2c_adapter *i2c_adap,
                       unsigned char addr, int retries)
 {
        struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
@@ -354,15 +353,11 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
                        return (retval<0)? retval : -EFAULT;
                                /* got a better one ?? */
                }
-#if 0
-               /* from asm/delay.h */
-               __delay(adap->mdelay * (loops_per_sec / 1000) );
-#endif
        }
        return wrcount;
 }
 
-static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
        int inval;
        int rdcount=0;          /* counts bytes read */
@@ -412,7 +407,7 @@ static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
  * -x an error occurred (like: -EREMOTEIO if the device did not answer, or
  *     -ETIMEDOUT, for example if the lines are stuck...) 
  */
-static inline int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) 
+static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
        unsigned short flags = msg->flags;
        unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
@@ -517,7 +512,7 @@ static u32 bit_func(struct i2c_adapter *adap)
 
 /* -----exported algorithm data: ------------------------------------- */
 
-static struct i2c_algorithm i2c_bit_algo = {
+static const struct i2c_algorithm i2c_bit_algo = {
        .master_xfer    = bit_xfer,
        .functionality  = bit_func,
 };
index b88a6fcf7bd094abf75c67ba940cefe0fbd9ce58..9081c9fbcd2940a84f82827ee39ba60f1e08d086 100644 (file)
@@ -355,7 +355,7 @@ static int pca_init(struct i2c_algo_pca_data *adap)
        return 0;
 }
 
-static struct i2c_algorithm pca_algo = {
+static const struct i2c_algorithm pca_algo = {
        .master_xfer    = pca_xfer,
        .functionality  = pca_func,
 };
index 5b24930adb5a7b9e23721f47aca79daa7b450d04..3b2003398966910ec80236ccef17a41e6fe0c71f 100644 (file)
@@ -458,7 +458,7 @@ static u32 pcf_func(struct i2c_adapter *adap)
 
 /* -----exported algorithm data: ------------------------------------- */
 
-static struct i2c_algorithm pcf_algo = {
+static const struct i2c_algorithm pcf_algo = {
        .master_xfer    = pcf_xfer,
        .functionality  = pcf_func,
 };
index 932c4fa86c7374eb9cf667ab14a8d20cc94adcbf..490d99997fd098ffd9aa65f5321cfc2700bc2f65 100644 (file)
@@ -157,7 +157,7 @@ static u32 sgi_func(struct i2c_adapter *adap)
        return I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm sgi_algo = {
+static const struct i2c_algorithm sgi_algo = {
        .master_xfer    = sgi_xfer,
        .functionality  = sgi_func,
 };
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
deleted file mode 100644 (file)
index 32d41c6..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/* i2c-algo-sibyte.c i2c driver algorithms for bit-shift adapters                   */
-/* ------------------------------------------------------------------------- */
-/*   Copyright (C) 2001,2002,2003 Broadcom Corporation
-     Copyright (C) 1995-2000 Simon G. Vogl
-
-    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.               */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
-   Frodo Looijaard <frodol@dds.nl>.  */
-
-/* Ported for SiByte SOCs by Broadcom Corporation.  */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_smbus.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-sibyte.h>
-
-/* ----- global defines ----------------------------------------------- */
-#define SMB_CSR(a,r) ((long)(a->reg_base + r))
-
-/* ----- global variables ---------------------------------------------        */
-
-/* module parameters:
- */
-static int bit_scan;   /* have a look at what's hanging 'round         */
-
-
-static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr, 
-                      unsigned short flags, char read_write,
-                      u8 command, int size, union i2c_smbus_data * data)
-{
-       struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
-        int data_bytes = 0;
-        int error;
-
-        while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-        switch (size) {
-        case I2C_SMBUS_QUICK:
-                csr_out32((V_SMB_ADDR(addr) | (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
-                          V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
-                break;
-        case I2C_SMBUS_BYTE:
-                if (read_write == I2C_SMBUS_READ) {
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                        data_bytes = 1;
-                } else {
-                        csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                }
-                break;
-        case I2C_SMBUS_BYTE_DATA:
-                csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
-                if (read_write == I2C_SMBUS_READ) {
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                        data_bytes = 1;
-                } else {
-                        csr_out32(V_SMB_LB(data->byte), SMB_CSR(adap, R_SMB_DATA));
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                }
-                break;
-        case I2C_SMBUS_WORD_DATA:
-                csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
-                if (read_write == I2C_SMBUS_READ) {
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                        data_bytes = 2;
-                } else {
-                        csr_out32(V_SMB_LB(data->word & 0xff), SMB_CSR(adap, R_SMB_DATA));
-                        csr_out32(V_SMB_MB(data->word >> 8), SMB_CSR(adap, R_SMB_DATA));
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
-                                 SMB_CSR(adap, R_SMB_START));
-                }
-                break;
-        default:
-                return -1;      /* XXXKW better error code? */
-        }
-
-        while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-        error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
-        if (error & M_SMB_ERROR) {
-                /* Clear error bit by writing a 1 */
-                csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
-                return -1;      /* XXXKW better error code? */
-        }
-
-        if (data_bytes == 1)
-                data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
-        if (data_bytes == 2)
-                data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
-
-        return 0;
-}
-
-static int algo_control(struct i2c_adapter *adapter, 
-       unsigned int cmd, unsigned long arg)
-{
-       return 0;
-}
-
-static u32 bit_func(struct i2c_adapter *adap)
-{
-       return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
-                I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
-}
-
-
-/* -----exported algorithm data: ------------------------------------- */
-
-static struct i2c_algorithm i2c_sibyte_algo = {
-       .smbus_xfer     = smbus_xfer,
-       .algo_control   = algo_control, /* ioctl */
-       .functionality  = bit_func,
-};
-
-/* 
- * registering functions to load algorithms at runtime 
- */
-int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
-{
-       int i;
-       struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
-
-       /* register new adapter to i2c module... */
-       i2c_adap->algo = &i2c_sibyte_algo;
-        
-        /* Set the frequency to 100 kHz */
-        csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
-        csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
-
-       /* scan bus */
-       if (bit_scan) {
-                union i2c_smbus_data data;
-                int rc;
-               printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
-                      i2c_adap->name);
-               for (i = 0x00; i < 0x7f; i++) {
-                        /* XXXKW is this a realistic probe? */
-                        rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
-                                        I2C_SMBUS_BYTE_DATA, &data);
-                       if (!rc) {
-                               printk("(%02x)",i); 
-                       } else 
-                               printk("."); 
-               }
-               printk("\n");
-       }
-
-       return i2c_add_adapter(i2c_adap);
-}
-
-
-int i2c_sibyte_del_bus(struct i2c_adapter *adap)
-{
-       int res;
-
-       if ((res = i2c_del_adapter(adap)) < 0)
-               return res;
-
-       return 0;
-}
-
-int __init i2c_algo_sibyte_init (void)
-{
-       printk("i2c-algo-sibyte.o: i2c SiByte algorithm module\n");
-       return 0;
-}
-
-
-EXPORT_SYMBOL(i2c_sibyte_add_bus);
-EXPORT_SYMBOL(i2c_sibyte_del_bus);
-
-#ifdef MODULE
-MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
-MODULE_DESCRIPTION("SiByte I2C-Bus algorithm");
-module_param(bit_scan, int, 0);
-MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
-MODULE_LICENSE("GPL");
-
-int init_module(void) 
-{
-       return i2c_algo_sibyte_init();
-}
-
-void cleanup_module(void) 
-{
-}
-#endif
index 884320e70403f0776b891e99332e6808f190a128..9e56c3989d680e7f022614989f7ec17b4661d00c 100644 (file)
@@ -75,11 +75,11 @@ config I2C_AMD8111
          will be called i2c-amd8111.
 
 config I2C_AU1550
-       tristate "Au1550 SMBus interface"
-       depends on I2C && SOC_AU1550
+       tristate "Au1550/Au1200 SMBus interface"
+       depends on I2C && (SOC_AU1550 || SOC_AU1200)
        help
          If you say yes to this option, support will be included for the
-         Au1550 SMBus interface.
+         Au1550 and Au1200 SMBus interface.
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-au1550.
@@ -287,6 +287,16 @@ config I2C_OCORES
          This driver can also be built as a module.  If so, the module
          will be called i2c-ocores.
 
+config I2C_OMAP
+       tristate "OMAP I2C adapter"
+       depends on I2C && ARCH_OMAP
+       default y if MACH_OMAP_H3 || MACH_OMAP_OSK
+       help
+         If you say yes to this option, support will be included for the
+         I2C interface on the Texas Instruments OMAP1/2 family of processors.
+         Like OMAP1510/1610/1710/5912 and OMAP242x.
+         For details see http://www.ti.com/omap.
+
 config I2C_PARPORT
        tristate "Parallel port adapter"
        depends on I2C && PARPORT
@@ -482,19 +492,19 @@ config I2C_VIA
          will be called i2c-via.
 
 config I2C_VIAPRO
-       tristate "VIA 82C596/82C686/823x"
+       tristate "VIA 82C596/82C686/82xx"
        depends on I2C && PCI
        help
          If you say yes to this option, support will be included for the VIA
-         82C596/82C686/823x I2C interfaces.  Specifically, the following 
+         82C596/82C686/82xx I2C interfaces.  Specifically, the following
          chipsets are supported:
-         82C596A/B
-         82C686A/B
-         8231
-         8233
-         8233A
-         8235
-         8237
+           VT82C596A/B
+           VT82C686A/B
+           VT8231
+           VT8233/A
+           VT8235
+           VT8237R/A
+           VT8251
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-viapro.
index ac56df53155baf0f0fa95bd9c2e8c5fec0d699ae..493c87289b6262fa0a02c46d19970479df71e9ab 100644 (file)
@@ -24,6 +24,7 @@ obj-$(CONFIG_I2C_MPC)         += i2c-mpc.o
 obj-$(CONFIG_I2C_MV64XXX)      += i2c-mv64xxx.o
 obj-$(CONFIG_I2C_NFORCE2)      += i2c-nforce2.o
 obj-$(CONFIG_I2C_OCORES)       += i2c-ocores.o
+obj-$(CONFIG_I2C_OMAP)         += i2c-omap.o
 obj-$(CONFIG_I2C_PARPORT)      += i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)        += i2c-parport-light.o
 obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
index d3ef46aeeb3ca5eb5a365d5a507f16146ecaba1b..e75d339a3481e9dcd03acb7dda20d14ba73352ae 100644 (file)
@@ -468,7 +468,7 @@ static u32 ali1535_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = ali1535_access,
        .functionality  = ali1535_func,
 };
index e6f63208fc4a631df15682ed6a32c3c5f68793bd..33fbb47100a36d02a45492cc8233301d66c4b7c1 100644 (file)
@@ -367,7 +367,7 @@ static void ali1563_shutdown(struct pci_dev *dev)
        release_region(ali1563_smba,ALI1563_SMB_IOSIZE);
 }
 
-static struct i2c_algorithm ali1563_algorithm = {
+static const struct i2c_algorithm ali1563_algorithm = {
        .smbus_xfer     = ali1563_access,
        .functionality  = ali1563_func,
 };
index 7a5c0941dbc13f396aaabaf5881f48eb0650761c..3f11b6e1a3418c5bc5dad86681b7eae67c429af7 100644 (file)
@@ -463,7 +463,7 @@ static u32 ali15x3_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = ali15x3_access,
        .functionality  = ali15x3_func,
 };
index 1750dedaf4b5620a553455778efd62d3bf9ca2fd..2d21afdc5b1cc7f3961c3e4f480de0444ec4292f 100644 (file)
@@ -294,7 +294,7 @@ static u32 amd756_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = amd756_access,
        .functionality  = amd756_func,
 };
index e5ef560e686ae8c5f8bdab1b8a2d38e0d90e933f..0fbc7186c91ab63f8ac8f6b32365db3a850efc6f 100644 (file)
@@ -316,7 +316,7 @@ static u32 amd8111_func(struct i2c_adapter *adapter)
                I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer = amd8111_access,
        .functionality = amd8111_func,
 };
index d06edce03bf40dd83604708018d4ce5165cd852f..d7e7c359fc364831a9ad1a0bed6001f2e88d9b41 100644 (file)
@@ -34,8 +34,7 @@
 #include <linux/errno.h>
 #include <linux/i2c.h>
 
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-pb1x00/pb1550.h>
+#include <asm/mach-au1x00/au1xxx.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 
 #include "i2c-au1550.h"
@@ -118,13 +117,19 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
 
        /* Reset the FIFOs, clear events.
        */
-       sp->psc_smbpcr = PSC_SMBPCR_DC;
+       stat = sp->psc_smbstat;
        sp->psc_smbevnt = PSC_SMBEVNT_ALLCLR;
        au_sync();
-       do {
-               stat = sp->psc_smbpcr;
+
+       if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
+               sp->psc_smbpcr = PSC_SMBPCR_DC;
                au_sync();
-       } while ((stat & PSC_SMBPCR_DC) != 0);
+               do {
+                       stat = sp->psc_smbpcr;
+                       au_sync();
+               } while ((stat & PSC_SMBPCR_DC) != 0);
+               udelay(50);
+       }
 
        /* Write out the i2c chip address and specify operation
        */
@@ -279,10 +284,10 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 static u32
 au1550_func(struct i2c_adapter *adap)
 {
-       return I2C_FUNC_I2C;
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm au1550_algo = {
+static const struct i2c_algorithm au1550_algo = {
        .master_xfer    = au1550_xfer,
        .functionality  = au1550_func,
 };
index 59f8308c2356cc834f9015074bfb196b4e09312b..caa8e5c8bfbbdc6f8d4cfc844b59237466867e6d 100644 (file)
@@ -196,7 +196,6 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
        .getclock   = pcf_isa_getclock,
        .waitforpin = pcf_isa_waitforpin,
        .udelay     = 10,
-       .mdelay     = 10,
        .timeout    = 100,
 };
 
index e0cb3b0f92faba50a64d40f437188f106aaa9c57..457d48a0ab9dcf0c3993917df67ccf924c899cd7 100644 (file)
@@ -99,7 +99,6 @@ static struct i2c_algo_bit_data hydra_bit_data = {
        .getsda         = hydra_bit_getsda,
        .getscl         = hydra_bit_getscl,
        .udelay         = 5,
-       .mdelay         = 5,
        .timeout        = HZ
 };
 
index 7be1d0a3e8f8f59856562013e1b6361d569c6510..bbb2fbee836fe45c855dfef454a66cecd560b213 100644 (file)
@@ -434,7 +434,7 @@ static u32 i801_func(struct i2c_adapter *adapter)
             | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = i801_access,
        .functionality  = i801_func,
 };
index 748be30f2bae3d740d35914dba90ba72f7b7f3bc..b66fb6bb18700d78068d1ee845ce392c27dce388 100644 (file)
@@ -166,7 +166,6 @@ static struct i2c_algo_bit_data i810_i2c_bit_data = {
        .getsda         = bit_i810i2c_getsda,
        .getscl         = bit_i810i2c_getscl,
        .udelay         = CYCLE_DELAY,
-       .mdelay         = CYCLE_DELAY,
        .timeout        = TIMEOUT,
 };
 
@@ -182,7 +181,6 @@ static struct i2c_algo_bit_data i810_ddc_bit_data = {
        .getsda         = bit_i810ddc_getsda,
        .getscl         = bit_i810ddc_getscl,
        .udelay         = CYCLE_DELAY,
-       .mdelay         = CYCLE_DELAY,
        .timeout        = TIMEOUT,
 };
 
index 0599bbd65d93b196fd946b1f270b89af48932730..5bccb5d68318b6ea5fdfc0387a3136138d8bb20b 100644 (file)
@@ -625,7 +625,7 @@ static u32 iic_func(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
 }
 
-static struct i2c_algorithm iic_algo = {
+static const struct i2c_algorithm iic_algo = {
        .master_xfer    = iic_xfer,
        .functionality  = iic_func
 };
index 48c56939c8619abaae4e6289fb86cd2856d03921..8e413150af37d1c11e8a647fbe6719132176e3da 100644 (file)
@@ -401,7 +401,7 @@ iop3xx_i2c_func(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm iop3xx_i2c_algo = {
+static const struct i2c_algorithm iop3xx_i2c_algo = {
        .master_xfer    = iop3xx_i2c_master_xfer,
        .algo_control   = iop3xx_i2c_algo_control,
        .functionality  = iop3xx_i2c_func,
index c3e1d3e888d7b25c20d90ae4a7ecb8f5be420b98..4380653748a4c155065bb057148f91e1e1b7eddd 100644 (file)
@@ -43,7 +43,7 @@
 static u32 isa_func(struct i2c_adapter *adapter);
 
 /* This is the actual algorithm we define */
-static struct i2c_algorithm isa_algorithm = {
+static const struct i2c_algorithm isa_algorithm = {
        .functionality  = isa_func,
 };
 
@@ -89,9 +89,14 @@ int i2c_isa_add_driver(struct i2c_driver *driver)
        dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->driver.name);
 
        /* Now look for clients */
-       driver->attach_adapter(&isa_adapter);
-
-       return 0;
+       res = driver->attach_adapter(&isa_adapter);
+       if (res) {
+               dev_err(&isa_adapter.dev,
+                       "Driver %s failed to attach adapter, unregistering\n",
+                       driver->driver.name);
+               driver_unregister(&driver->driver);
+       }
+       return res;
 }
 
 int i2c_isa_del_driver(struct i2c_driver *driver)
@@ -125,6 +130,8 @@ int i2c_isa_del_driver(struct i2c_driver *driver)
 
 static int __init i2c_isa_init(void)
 {
+       int err;
+
        mutex_init(&isa_adapter.clist_lock);
        INIT_LIST_HEAD(&isa_adapter.clients);
 
@@ -133,8 +140,16 @@ static int __init i2c_isa_init(void)
        sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
        isa_adapter.dev.driver = &i2c_adapter_driver;
        isa_adapter.dev.release = &i2c_adapter_dev_release;
-       device_register(&isa_adapter.dev);
-       device_create_file(&isa_adapter.dev, &dev_attr_name);
+       err = device_register(&isa_adapter.dev);
+       if (err) {
+               printk(KERN_ERR "i2c-isa: Failed to register device\n");
+               goto exit;
+       }
+       err = device_create_file(&isa_adapter.dev, &dev_attr_name);
+       if (err) {
+               printk(KERN_ERR "i2c-isa: Failed to create name file\n");
+               goto exit_unregister;
+       }
 
        /* Add this adapter to the i2c_adapter class */
        memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
@@ -142,11 +157,24 @@ static int __init i2c_isa_init(void)
        isa_adapter.class_dev.class = &i2c_adapter_class;
        strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
                BUS_ID_SIZE);
-       class_device_register(&isa_adapter.class_dev);
+       err = class_device_register(&isa_adapter.class_dev);
+       if (err) {
+               printk(KERN_ERR "i2c-isa: Failed to register class device\n");
+               goto exit_remove_name;
+       }
 
        dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
 
        return 0;
+
+exit_remove_name:
+       device_remove_file(&isa_adapter.dev, &dev_attr_name);
+exit_unregister:
+       init_completion(&isa_adapter.dev_released); /* Needed? */
+       device_unregister(&isa_adapter.dev);
+       wait_for_completion(&isa_adapter.dev_released);
+exit:
+       return err;
 }
 
 static void __exit i2c_isa_exit(void)
index cd6f45d186ab4d6a3b51ade91cf7bbb8f68a4f3a..dd3f4cd3aa6849cc7945b379705608f18d1f72a2 100644 (file)
@@ -114,7 +114,6 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
        drv_data->algo_data.getsda = ixp2000_bit_getsda;
        drv_data->algo_data.getscl = ixp2000_bit_getscl;
        drv_data->algo_data.udelay = 6;
-       drv_data->algo_data.mdelay = 6;
        drv_data->algo_data.timeout = 100;
 
        drv_data->adapter.id = I2C_HW_B_IXP2000,
index 2ed07112d683fa7cd1c72b0a31a7e95c6645543d..ab573254a8aa305c1703f4005b9477e296819397 100644 (file)
@@ -122,7 +122,6 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
        drv_data->algo_data.getsda = ixp4xx_bit_getsda;
        drv_data->algo_data.getscl = ixp4xx_bit_getscl;
        drv_data->algo_data.udelay = 10;
-       drv_data->algo_data.mdelay = 10;
        drv_data->algo_data.timeout = 100;
 
        drv_data->adapter.id = I2C_HW_B_IXP4XX;
index 377ab40944b8d3cbecfc02ab3c0fe1fb7673ec7c..155a986de516616d2ed5d70074cb28240a1878dd 100644 (file)
@@ -272,7 +272,7 @@ static u32 mpc_functionality(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm mpc_algo = {
+static const struct i2c_algorithm mpc_algo = {
        .master_xfer = mpc_xfer,
        .functionality = mpc_functionality,
 };
index ac5cde1bbd2ba24333d2360ce3b253d60a3426c8..eacbaf745b64527798c74fc5ddd48acdbd8e11b6 100644 (file)
@@ -431,7 +431,7 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        return num;
 }
 
-static struct i2c_algorithm mv64xxx_i2c_algo = {
+static const struct i2c_algorithm mv64xxx_i2c_algo = {
        .master_xfer = mv64xxx_i2c_xfer,
        .functionality = mv64xxx_i2c_functionality,
 };
index 604b49e22df144748da5b9e4b29a8c53287bec7c..e0292e414ab2ccadb5110cc6e94af0827b0adcce 100644 (file)
@@ -109,7 +109,7 @@ static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
 static u32 nforce2_func(struct i2c_adapter *adapter);
 
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer = nforce2_access,
        .functionality = nforce2_func,
 };
index 592824087c490d4c488fbf1b9841701fb18c9eb4..952a28d485ce9e593b26f6d7d4b7336582c11564 100644 (file)
@@ -199,7 +199,7 @@ static u32 ocores_func(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm ocores_algorithm = {
+static const struct i2c_algorithm ocores_algorithm = {
        .master_xfer    = ocores_xfer,
        .functionality  = ocores_func,
 };
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
new file mode 100644 (file)
index 0000000..81d87d2
--- /dev/null
@@ -0,0 +1,676 @@
+/*
+ * TI OMAP I2C master mode driver
+ *
+ * Copyright (C) 2003 MontaVista Software, Inc.
+ * Copyright (C) 2004 Texas Instruments.
+ *
+ * Updated to work with multiple I2C interfaces on 24xx by
+ * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * Cleaned up by Juha Yrjölä <juha.yrjola@nokia.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+
+/* timeout waiting for the controller to respond */
+#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
+
+#define OMAP_I2C_REV_REG               0x00
+#define OMAP_I2C_IE_REG                        0x04
+#define OMAP_I2C_STAT_REG              0x08
+#define OMAP_I2C_IV_REG                        0x0c
+#define OMAP_I2C_SYSS_REG              0x10
+#define OMAP_I2C_BUF_REG               0x14
+#define OMAP_I2C_CNT_REG               0x18
+#define OMAP_I2C_DATA_REG              0x1c
+#define OMAP_I2C_SYSC_REG              0x20
+#define OMAP_I2C_CON_REG               0x24
+#define OMAP_I2C_OA_REG                        0x28
+#define OMAP_I2C_SA_REG                        0x2c
+#define OMAP_I2C_PSC_REG               0x30
+#define OMAP_I2C_SCLL_REG              0x34
+#define OMAP_I2C_SCLH_REG              0x38
+#define OMAP_I2C_SYSTEST_REG           0x3c
+
+/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
+#define OMAP_I2C_IE_XRDY       (1 << 4)        /* TX data ready int enable */
+#define OMAP_I2C_IE_RRDY       (1 << 3)        /* RX data ready int enable */
+#define OMAP_I2C_IE_ARDY       (1 << 2)        /* Access ready int enable */
+#define OMAP_I2C_IE_NACK       (1 << 1)        /* No ack interrupt enable */
+#define OMAP_I2C_IE_AL         (1 << 0)        /* Arbitration lost int ena */
+
+/* I2C Status Register (OMAP_I2C_STAT): */
+#define OMAP_I2C_STAT_SBD      (1 << 15)       /* Single byte data */
+#define OMAP_I2C_STAT_BB       (1 << 12)       /* Bus busy */
+#define OMAP_I2C_STAT_ROVR     (1 << 11)       /* Receive overrun */
+#define OMAP_I2C_STAT_XUDF     (1 << 10)       /* Transmit underflow */
+#define OMAP_I2C_STAT_AAS      (1 << 9)        /* Address as slave */
+#define OMAP_I2C_STAT_AD0      (1 << 8)        /* Address zero */
+#define OMAP_I2C_STAT_XRDY     (1 << 4)        /* Transmit data ready */
+#define OMAP_I2C_STAT_RRDY     (1 << 3)        /* Receive data ready */
+#define OMAP_I2C_STAT_ARDY     (1 << 2)        /* Register access ready */
+#define OMAP_I2C_STAT_NACK     (1 << 1)        /* No ack interrupt enable */
+#define OMAP_I2C_STAT_AL       (1 << 0)        /* Arbitration lost int ena */
+
+/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
+#define OMAP_I2C_BUF_RDMA_EN   (1 << 15)       /* RX DMA channel enable */
+#define OMAP_I2C_BUF_XDMA_EN   (1 << 7)        /* TX DMA channel enable */
+
+/* I2C Configuration Register (OMAP_I2C_CON): */
+#define OMAP_I2C_CON_EN                (1 << 15)       /* I2C module enable */
+#define OMAP_I2C_CON_BE                (1 << 14)       /* Big endian mode */
+#define OMAP_I2C_CON_STB       (1 << 11)       /* Start byte mode (master) */
+#define OMAP_I2C_CON_MST       (1 << 10)       /* Master/slave mode */
+#define OMAP_I2C_CON_TRX       (1 << 9)        /* TX/RX mode (master only) */
+#define OMAP_I2C_CON_XA                (1 << 8)        /* Expand address */
+#define OMAP_I2C_CON_RM                (1 << 2)        /* Repeat mode (master only) */
+#define OMAP_I2C_CON_STP       (1 << 1)        /* Stop cond (master only) */
+#define OMAP_I2C_CON_STT       (1 << 0)        /* Start condition (master) */
+
+/* I2C System Test Register (OMAP_I2C_SYSTEST): */
+#ifdef DEBUG
+#define OMAP_I2C_SYSTEST_ST_EN         (1 << 15)       /* System test enable */
+#define OMAP_I2C_SYSTEST_FREE          (1 << 14)       /* Free running mode */
+#define OMAP_I2C_SYSTEST_TMODE_MASK    (3 << 12)       /* Test mode select */
+#define OMAP_I2C_SYSTEST_TMODE_SHIFT   (12)            /* Test mode select */
+#define OMAP_I2C_SYSTEST_SCL_I         (1 << 3)        /* SCL line sense in */
+#define OMAP_I2C_SYSTEST_SCL_O         (1 << 2)        /* SCL line drive out */
+#define OMAP_I2C_SYSTEST_SDA_I         (1 << 1)        /* SDA line sense in */
+#define OMAP_I2C_SYSTEST_SDA_O         (1 << 0)        /* SDA line drive out */
+#endif
+
+/* I2C System Status register (OMAP_I2C_SYSS): */
+#define OMAP_I2C_SYSS_RDONE            (1 << 0)        /* Reset Done */
+
+/* I2C System Configuration Register (OMAP_I2C_SYSC): */
+#define OMAP_I2C_SYSC_SRST             (1 << 1)        /* Soft Reset */
+
+/* REVISIT: Use platform_data instead of module parameters */
+/* Fast Mode = 400 kHz, Standard = 100 kHz */
+static int clock = 100; /* Default: 100 kHz */
+module_param(clock, int, 0);
+MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)");
+
+struct omap_i2c_dev {
+       struct device           *dev;
+       void __iomem            *base;          /* virtual */
+       int                     irq;
+       struct clk              *iclk;          /* Interface clock */
+       struct clk              *fclk;          /* Functional clock */
+       struct completion       cmd_complete;
+       struct resource         *ioarea;
+       u16                     cmd_err;
+       u8                      *buf;
+       size_t                  buf_len;
+       struct i2c_adapter      adapter;
+       unsigned                rev1:1;
+};
+
+static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
+                                     int reg, u16 val)
+{
+       __raw_writew(val, i2c_dev->base + reg);
+}
+
+static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
+{
+       return __raw_readw(i2c_dev->base + reg);
+}
+
+static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
+{
+       if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+               dev->iclk = clk_get(dev->dev, "i2c_ick");
+               if (IS_ERR(dev->iclk)) {
+                       dev->iclk = NULL;
+                       return -ENODEV;
+               }
+       }
+
+       dev->fclk = clk_get(dev->dev, "i2c_fck");
+       if (IS_ERR(dev->fclk)) {
+               if (dev->iclk != NULL) {
+                       clk_put(dev->iclk);
+                       dev->iclk = NULL;
+               }
+               dev->fclk = NULL;
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
+{
+       clk_put(dev->fclk);
+       dev->fclk = NULL;
+       if (dev->iclk != NULL) {
+               clk_put(dev->iclk);
+               dev->iclk = NULL;
+       }
+}
+
+static void omap_i2c_enable_clocks(struct omap_i2c_dev *dev)
+{
+       if (dev->iclk != NULL)
+               clk_enable(dev->iclk);
+       clk_enable(dev->fclk);
+}
+
+static void omap_i2c_disable_clocks(struct omap_i2c_dev *dev)
+{
+       if (dev->iclk != NULL)
+               clk_disable(dev->iclk);
+       clk_disable(dev->fclk);
+}
+
+static int omap_i2c_init(struct omap_i2c_dev *dev)
+{
+       u16 psc = 0;
+       unsigned long fclk_rate = 12000000;
+       unsigned long timeout;
+
+       if (!dev->rev1) {
+               omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
+               /* For some reason we need to set the EN bit before the
+                * reset done bit gets set. */
+               timeout = jiffies + OMAP_I2C_TIMEOUT;
+               omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+               while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
+                        OMAP_I2C_SYSS_RDONE)) {
+                       if (time_after(jiffies, timeout)) {
+                               dev_warn(dev->dev, "timeout waiting"
+                                               "for controller reset\n");
+                               return -ETIMEDOUT;
+                       }
+                       msleep(1);
+               }
+       }
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+
+       if (cpu_class_is_omap1()) {
+               struct clk *armxor_ck;
+
+               armxor_ck = clk_get(NULL, "armxor_ck");
+               if (IS_ERR(armxor_ck))
+                       dev_warn(dev->dev, "Could not get armxor_ck\n");
+               else {
+                       fclk_rate = clk_get_rate(armxor_ck);
+                       clk_put(armxor_ck);
+               }
+               /* TRM for 5912 says the I2C clock must be prescaled to be
+                * between 7 - 12 MHz. The XOR input clock is typically
+                * 12, 13 or 19.2 MHz. So we should have code that produces:
+                *
+                * XOR MHz      Divider         Prescaler
+                * 12           1               0
+                * 13           2               1
+                * 19.2         2               1
+                */
+               if (fclk_rate > 16000000)
+                       psc = (fclk_rate + 8000000) / 12000000;
+       }
+
+       /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
+       omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
+
+       /* Program desired operating rate */
+       fclk_rate /= (psc + 1) * 1000;
+       if (psc > 2)
+               psc = 2;
+
+       omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
+                          fclk_rate / (clock * 2) - 7 + psc);
+       omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
+                          fclk_rate / (clock * 2) - 7 + psc);
+
+       /* Take the I2C module out of reset: */
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+
+       /* Enable interrupts */
+       omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
+                          (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
+                           OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
+                           OMAP_I2C_IE_AL));
+       return 0;
+}
+
+/*
+ * Waiting on Bus Busy
+ */
+static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
+{
+       unsigned long timeout;
+
+       timeout = jiffies + OMAP_I2C_TIMEOUT;
+       while (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
+               if (time_after(jiffies, timeout)) {
+                       dev_warn(dev->dev, "timeout waiting for bus ready\n");
+                       return -ETIMEDOUT;
+               }
+               msleep(1);
+       }
+
+       return 0;
+}
+
+/*
+ * Low level master read/write transaction.
+ */
+static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
+                            struct i2c_msg *msg, int stop)
+{
+       struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
+       int r;
+       u16 w;
+
+       dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
+               msg->addr, msg->len, msg->flags, stop);
+
+       if (msg->len == 0)
+               return -EINVAL;
+
+       omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr);
+
+       /* REVISIT: Could the STB bit of I2C_CON be used with probing? */
+       dev->buf = msg->buf;
+       dev->buf_len = msg->len;
+
+       omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
+
+       init_completion(&dev->cmd_complete);
+       dev->cmd_err = 0;
+
+       w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
+       if (msg->flags & I2C_M_TEN)
+               w |= OMAP_I2C_CON_XA;
+       if (!(msg->flags & I2C_M_RD))
+               w |= OMAP_I2C_CON_TRX;
+       if (stop)
+               w |= OMAP_I2C_CON_STP;
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+
+       r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
+                                                     OMAP_I2C_TIMEOUT);
+       dev->buf_len = 0;
+       if (r < 0)
+               return r;
+       if (r == 0) {
+               dev_err(dev->dev, "controller timed out\n");
+               omap_i2c_init(dev);
+               return -ETIMEDOUT;
+       }
+
+       if (likely(!dev->cmd_err))
+               return 0;
+
+       /* We have an error */
+       if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR |
+                           OMAP_I2C_STAT_XUDF)) {
+               omap_i2c_init(dev);
+               return -EIO;
+       }
+
+       if (dev->cmd_err & OMAP_I2C_STAT_NACK) {
+               if (msg->flags & I2C_M_IGNORE_NAK)
+                       return 0;
+               if (stop) {
+                       w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+                       w |= OMAP_I2C_CON_STP;
+                       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+               }
+               return -EREMOTEIO;
+       }
+       return -EIO;
+}
+
+
+/*
+ * Prepare controller for a transaction and call omap_i2c_xfer_msg
+ * to do the work during IRQ processing.
+ */
+static int
+omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+       struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
+       int i;
+       int r;
+
+       omap_i2c_enable_clocks(dev);
+
+       /* REVISIT: initialize and use adap->retries. This is an optional
+        * feature */
+       if ((r = omap_i2c_wait_for_bb(dev)) < 0)
+               goto out;
+
+       for (i = 0; i < num; i++) {
+               r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
+               if (r != 0)
+                       break;
+       }
+
+       if (r == 0)
+               r = num;
+out:
+       omap_i2c_disable_clocks(dev);
+       return r;
+}
+
+static u32
+omap_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+}
+
+static inline void
+omap_i2c_complete_cmd(struct omap_i2c_dev *dev, u16 err)
+{
+       dev->cmd_err |= err;
+       complete(&dev->cmd_complete);
+}
+
+static inline void
+omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
+{
+       omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
+}
+
+static irqreturn_t
+omap_i2c_rev1_isr(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+       struct omap_i2c_dev *dev = dev_id;
+       u16 iv, w;
+
+       iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
+       switch (iv) {
+       case 0x00:      /* None */
+               break;
+       case 0x01:      /* Arbitration lost */
+               dev_err(dev->dev, "Arbitration lost\n");
+               omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
+               break;
+       case 0x02:      /* No acknowledgement */
+               omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
+               omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_STP);
+               break;
+       case 0x03:      /* Register access ready */
+               omap_i2c_complete_cmd(dev, 0);
+               break;
+       case 0x04:      /* Receive data ready */
+               if (dev->buf_len) {
+                       w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+                       *dev->buf++ = w;
+                       dev->buf_len--;
+                       if (dev->buf_len) {
+                               *dev->buf++ = w >> 8;
+                               dev->buf_len--;
+                       }
+               } else
+                       dev_err(dev->dev, "RRDY IRQ while no data requested\n");
+               break;
+       case 0x05:      /* Transmit data ready */
+               if (dev->buf_len) {
+                       w = *dev->buf++;
+                       dev->buf_len--;
+                       if (dev->buf_len) {
+                               w |= *dev->buf++ << 8;
+                               dev->buf_len--;
+                       }
+                       omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+               } else
+                       dev_err(dev->dev, "XRDY IRQ while no data to send\n");
+               break;
+       default:
+               return IRQ_NONE;
+       }
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t
+omap_i2c_isr(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+       struct omap_i2c_dev *dev = dev_id;
+       u16 bits;
+       u16 stat, w;
+       int count = 0;
+
+       bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
+       while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) {
+               dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat);
+               if (count++ == 100) {
+                       dev_warn(dev->dev, "Too much work in one IRQ\n");
+                       break;
+               }
+
+               omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
+
+               if (stat & OMAP_I2C_STAT_ARDY) {
+                       omap_i2c_complete_cmd(dev, 0);
+                       continue;
+               }
+               if (stat & OMAP_I2C_STAT_RRDY) {
+                       w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+                       if (dev->buf_len) {
+                               *dev->buf++ = w;
+                               dev->buf_len--;
+                               if (dev->buf_len) {
+                                       *dev->buf++ = w >> 8;
+                                       dev->buf_len--;
+                               }
+                       } else
+                               dev_err(dev->dev, "RRDY IRQ while no data"
+                                               "requested\n");
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
+                       continue;
+               }
+               if (stat & OMAP_I2C_STAT_XRDY) {
+                       w = 0;
+                       if (dev->buf_len) {
+                               w = *dev->buf++;
+                               dev->buf_len--;
+                               if (dev->buf_len) {
+                                       w |= *dev->buf++ << 8;
+                                       dev->buf_len--;
+                               }
+                       } else
+                               dev_err(dev->dev, "XRDY IRQ while no"
+                                       "data to send\n");
+                       omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+                       omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
+                       continue;
+               }
+               if (stat & OMAP_I2C_STAT_ROVR) {
+                       dev_err(dev->dev, "Receive overrun\n");
+                       dev->cmd_err |= OMAP_I2C_STAT_ROVR;
+               }
+               if (stat & OMAP_I2C_STAT_XUDF) {
+                       dev_err(dev->dev, "Transmit overflow\n");
+                       dev->cmd_err |= OMAP_I2C_STAT_XUDF;
+               }
+               if (stat & OMAP_I2C_STAT_NACK) {
+                       omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
+                       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+                                          OMAP_I2C_CON_STP);
+               }
+               if (stat & OMAP_I2C_STAT_AL) {
+                       dev_err(dev->dev, "Arbitration lost\n");
+                       omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
+               }
+       }
+
+       return count ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static const struct i2c_algorithm omap_i2c_algo = {
+       .master_xfer    = omap_i2c_xfer,
+       .functionality  = omap_i2c_func,
+};
+
+static int
+omap_i2c_probe(struct platform_device *pdev)
+{
+       struct omap_i2c_dev     *dev;
+       struct i2c_adapter      *adap;
+       struct resource         *mem, *irq, *ioarea;
+       int r;
+
+       /* NOTE: driver uses the static register mapping */
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(&pdev->dev, "no mem resource?\n");
+               return -ENODEV;
+       }
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!irq) {
+               dev_err(&pdev->dev, "no irq resource?\n");
+               return -ENODEV;
+       }
+
+       ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+                       pdev->name);
+       if (!ioarea) {
+               dev_err(&pdev->dev, "I2C region already claimed\n");
+               return -EBUSY;
+       }
+
+       if (clock > 200)
+               clock = 400;    /* Fast mode */
+       else
+               clock = 100;    /* Standard mode */
+
+       dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
+       if (!dev) {
+               r = -ENOMEM;
+               goto err_release_region;
+       }
+
+       dev->dev = &pdev->dev;
+       dev->irq = irq->start;
+       dev->base = (void __iomem *) IO_ADDRESS(mem->start);
+       platform_set_drvdata(pdev, dev);
+
+       if ((r = omap_i2c_get_clocks(dev)) != 0)
+               goto err_free_mem;
+
+       omap_i2c_enable_clocks(dev);
+
+       if (cpu_is_omap15xx())
+               dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
+
+       /* reset ASAP, clearing any IRQs */
+       omap_i2c_init(dev);
+
+       r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr,
+                       0, pdev->name, dev);
+
+       if (r) {
+               dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
+               goto err_unuse_clocks;
+       }
+       r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+       dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
+                pdev->id, r >> 4, r & 0xf, clock);
+
+       adap = &dev->adapter;
+       i2c_set_adapdata(adap, dev);
+       adap->owner = THIS_MODULE;
+       adap->class = I2C_CLASS_HWMON;
+       strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
+       adap->algo = &omap_i2c_algo;
+       adap->dev.parent = &pdev->dev;
+
+       /* i2c device drivers may be active on return from add_adapter() */
+       r = i2c_add_adapter(adap);
+       if (r) {
+               dev_err(dev->dev, "failure adding adapter\n");
+               goto err_free_irq;
+       }
+
+       omap_i2c_disable_clocks(dev);
+
+       return 0;
+
+err_free_irq:
+       free_irq(dev->irq, dev);
+err_unuse_clocks:
+       omap_i2c_disable_clocks(dev);
+       omap_i2c_put_clocks(dev);
+err_free_mem:
+       platform_set_drvdata(pdev, NULL);
+       kfree(dev);
+err_release_region:
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+
+       return r;
+}
+
+static int
+omap_i2c_remove(struct platform_device *pdev)
+{
+       struct omap_i2c_dev     *dev = platform_get_drvdata(pdev);
+       struct resource         *mem;
+
+       platform_set_drvdata(pdev, NULL);
+
+       free_irq(dev->irq, dev);
+       i2c_del_adapter(&dev->adapter);
+       omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+       omap_i2c_put_clocks(dev);
+       kfree(dev);
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       return 0;
+}
+
+static struct platform_driver omap_i2c_driver = {
+       .probe          = omap_i2c_probe,
+       .remove         = omap_i2c_remove,
+       .driver         = {
+               .name   = "i2c_omap",
+               .owner  = THIS_MODULE,
+       },
+};
+
+/* I2C may be needed to bring up other drivers */
+static int __init
+omap_i2c_init_driver(void)
+{
+       return platform_driver_register(&omap_i2c_driver);
+}
+subsys_initcall(omap_i2c_init_driver);
+
+static void __exit omap_i2c_exit_driver(void)
+{
+       platform_driver_unregister(&omap_i2c_driver);
+}
+module_exit(omap_i2c_exit_driver);
+
+MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
+MODULE_DESCRIPTION("TI OMAP I2C bus adapter");
+MODULE_LICENSE("GPL");
index e09ebbb2f9f09dc14dc00129211c82cfd4da95cb..5eb2bd294fd97478f78592e26bcb6dd75e027b1e 100644 (file)
@@ -103,7 +103,6 @@ static struct i2c_algo_bit_data parport_algo_data = {
        .getsda         = parport_getsda,
        .getscl         = parport_getscl,
        .udelay         = 50,
-       .mdelay         = 50,
        .timeout        = HZ,
 }; 
 
index 934bd55bae15da1164ca7b14b79a5c7bb2cfcf18..48a829431c7bd1dcdb481776f9dd6e993d3df1c1 100644 (file)
@@ -138,7 +138,6 @@ static struct i2c_algo_bit_data parport_algo_data = {
        .getsda         = parport_getsda,
        .getscl         = parport_getscl,
        .udelay         = 60,
-       .mdelay         = 60,
        .timeout        = HZ,
 }; 
 
index 8f2f65b793b9a355e5f8b0022cd42711e0755644..30c7a1b38cbd7e5202106b8f060bb55a83f29e5d 100644 (file)
@@ -376,7 +376,7 @@ static u32 piix4_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = piix4_access,
        .functionality  = piix4_func,
 };
index d658d91079550d56f8c38bd8f31dce1c6e415160..a508cb962d244e89b4addc108f2c159212639364 100644 (file)
@@ -175,7 +175,7 @@ static u32 i2c_powermac_func(struct i2c_adapter * adapter)
 }
 
 /* For now, we only handle smbus */
-static struct i2c_algorithm i2c_powermac_algorithm = {
+static const struct i2c_algorithm i2c_powermac_algorithm = {
        .smbus_xfer     = i2c_powermac_smbus_xfer,
        .master_xfer    = i2c_powermac_master_xfer,
        .functionality  = i2c_powermac_func,
index 9479525892e3e337d0872eef7f630041776bf0ff..7745e21874a8e145c8caa5b0a1a9fea44fd32fac 100644 (file)
@@ -180,7 +180,6 @@ static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iom
        p->algo.getsda    = bit_s3via_getsda;
        p->algo.getscl    = bit_s3via_getscl;
        p->algo.udelay    = CYCLE_DELAY;
-       p->algo.mdelay    = CYCLE_DELAY;
        p->algo.timeout   = TIMEOUT;
        p->algo.data      = p;
        p->mmvga          = mmvga;
index ee114b48face4e2662f85cd4b6ab09f697b03656..cd4ad98ad517f9f0315208564922dfef8d69fffe 100644 (file)
@@ -926,7 +926,7 @@ static u32 i2c_pxa_functionality(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm i2c_pxa_algorithm = {
+static const struct i2c_algorithm i2c_pxa_algorithm = {
        .master_xfer    = i2c_pxa_xfer,
        .functionality  = i2c_pxa_functionality,
 };
index 5d2950e91fc5fce62a6e3566791abcf2b1738d4c..9ebe429a0a0ffd2fc853b6268e5e1e0d1be1738d 100644 (file)
@@ -566,7 +566,7 @@ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
 
 /* i2c bus registration info */
 
-static struct i2c_algorithm s3c24xx_i2c_algorithm = {
+static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
        .master_xfer            = s3c24xx_i2c_xfer,
        .functionality          = s3c24xx_i2c_func,
 };
index 0c8518298e4da3da0df6188849c6b3881393dabf..209f47ea175057c7ed3816dd294a4f9d9f6f52a4 100644 (file)
@@ -140,7 +140,6 @@ static struct i2c_algo_bit_data sav_i2c_bit_data = {
        .getsda         = bit_savi2c_getsda,
        .getscl         = bit_savi2c_getscl,
        .udelay         = CYCLE_DELAY,
-       .mdelay         = CYCLE_DELAY,
        .timeout        = TIMEOUT
 };
 
index fa503ed9f86db6d8fb32899d817a9db78d6e60f7..8f2b1f0deb813b6876fa233c525094ea522e1cf7 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2004 Steven J. Hill
  * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ * Copyright (C) 1995-2000 Simon G. Vogl
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/i2c-algo-sibyte.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <asm/io.h>
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_smbus.h>
 
+
+struct i2c_algo_sibyte_data {
+       void *data;             /* private data */
+       int   bus;              /* which bus */
+       void *reg_base;         /* CSR base */
+};
+
+/* ----- global defines ----------------------------------------------- */
+#define SMB_CSR(a,r) ((long)(a->reg_base + r))
+
+/* ----- global variables --------------------------------------------- */
+
+/* module parameters:
+ */
+static int bit_scan;   /* have a look at what's hanging 'round */
+module_param(bit_scan, int, 0);
+MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
+
+
+static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
+                     unsigned short flags, char read_write,
+                     u8 command, int size, union i2c_smbus_data * data)
+{
+       struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+       int data_bytes = 0;
+       int error;
+
+       while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
+               ;
+
+       switch (size) {
+       case I2C_SMBUS_QUICK:
+               csr_out32((V_SMB_ADDR(addr) |
+                          (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
+                          V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
+               break;
+       case I2C_SMBUS_BYTE:
+               if (read_write == I2C_SMBUS_READ) {
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+                       data_bytes = 1;
+               } else {
+                       csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+               }
+               break;
+       case I2C_SMBUS_BYTE_DATA:
+               csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+               if (read_write == I2C_SMBUS_READ) {
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+                       data_bytes = 1;
+               } else {
+                       csr_out32(V_SMB_LB(data->byte),
+                                 SMB_CSR(adap, R_SMB_DATA));
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+               }
+               break;
+       case I2C_SMBUS_WORD_DATA:
+               csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+               if (read_write == I2C_SMBUS_READ) {
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+                       data_bytes = 2;
+               } else {
+                       csr_out32(V_SMB_LB(data->word & 0xff),
+                                 SMB_CSR(adap, R_SMB_DATA));
+                       csr_out32(V_SMB_MB(data->word >> 8),
+                                 SMB_CSR(adap, R_SMB_DATA));
+                       csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
+                                 SMB_CSR(adap, R_SMB_START));
+               }
+               break;
+       default:
+               return -1;      /* XXXKW better error code? */
+       }
+
+       while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
+               ;
+
+       error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
+       if (error & M_SMB_ERROR) {
+               /* Clear error bit by writing a 1 */
+               csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
+               return -1;      /* XXXKW better error code? */
+       }
+
+       if (data_bytes == 1)
+               data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
+       if (data_bytes == 2)
+               data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
+
+       return 0;
+}
+
+static u32 bit_func(struct i2c_adapter *adap)
+{
+       return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+               I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
+}
+
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static const struct i2c_algorithm i2c_sibyte_algo = {
+       .smbus_xfer     = smbus_xfer,
+       .functionality  = bit_func,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
+{
+       int i;
+       struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+
+       /* register new adapter to i2c module... */
+       i2c_adap->algo = &i2c_sibyte_algo;
+
+       /* Set the frequency to 100 kHz */
+       csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
+       csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
+
+       /* scan bus */
+       if (bit_scan) {
+               union i2c_smbus_data data;
+               int rc;
+               printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
+                      i2c_adap->name);
+               for (i = 0x00; i < 0x7f; i++) {
+                       /* XXXKW is this a realistic probe? */
+                       rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
+                                       I2C_SMBUS_BYTE_DATA, &data);
+                       if (!rc) {
+                               printk("(%02x)",i);
+                       } else
+                               printk(".");
+               }
+               printk("\n");
+       }
+
+       return i2c_add_adapter(i2c_adap);
+}
+
+
 static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
        { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) },
        { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) }
@@ -58,13 +210,13 @@ static int __init i2c_sibyte_init(void)
 
 static void __exit i2c_sibyte_exit(void)
 {
-       i2c_sibyte_del_bus(&sibyte_board_adapter[0]);
-       i2c_sibyte_del_bus(&sibyte_board_adapter[1]);
+       i2c_del_bus(&sibyte_board_adapter[0]);
+       i2c_del_bus(&sibyte_board_adapter[1]);
 }
 
 module_init(i2c_sibyte_init);
 module_exit(i2c_sibyte_exit);
 
-MODULE_AUTHOR("Kip Walker <kwalker@broadcom.com>, Steven J. Hill <sjhill@realitydiluted.com>");
+MODULE_AUTHOR("Kip Walker (Broadcom Corp.), Steven J. Hill <sjhill@realitydiluted.com>");
 MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards");
 MODULE_LICENSE("GPL");
index b57ab74d23ecaa42c14ff8d0a22a225766ba7c12..38bbfd840b6b181c51aab35856ceebfdfb737cdf 100644 (file)
@@ -358,7 +358,7 @@ static u32 sis5595_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_PROC_CALL;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = sis5595_access,
        .functionality  = sis5595_func,
 };
index acb75e2824140220fcea0b4e010fac3e0c69f0fb..dec0bafb52ab5cd5f241b7675800048a790c7cd8 100644 (file)
@@ -450,7 +450,7 @@ exit:
 }
 
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = sis630_access,
        .functionality  = sis630_func,
 };
index 1a73c0532fc770bb6c1f812ba7959cdc511427b5..7fd07fbac33681c3f81f49e66acad11660aa3533 100644 (file)
@@ -242,7 +242,7 @@ static u32 sis96x_func(struct i2c_adapter *adapter)
            I2C_FUNC_SMBUS_PROC_CALL;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = sis96x_access,
        .functionality  = sis96x_func,
 };
index 73f481e93a36458c3040e391d3a16ac649d9affd..a54adc50d162a5a580ae60a709b87bb802280c75 100644 (file)
 #include <linux/errno.h>
 #include <linux/i2c.h>
 
+static unsigned short chip_addr;
+module_param(chip_addr, ushort, S_IRUGO);
+MODULE_PARM_DESC(chip_addr, "Chip address (between 0x03 and 0x77)\n");
+
 static u8  stub_pointer;
 static u8  stub_bytes[256];
 static u16 stub_words[256];
@@ -37,6 +41,9 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
 {
        s32 ret;
 
+       if (addr != chip_addr)
+               return -ENODEV;
+
        switch (size) {
 
        case I2C_SMBUS_QUICK:
@@ -108,7 +115,7 @@ static u32 stub_func(struct i2c_adapter *adapter)
                I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .functionality  = stub_func,
        .smbus_xfer     = stub_xfer,
 };
@@ -122,7 +129,17 @@ static struct i2c_adapter stub_adapter = {
 
 static int __init i2c_stub_init(void)
 {
-       printk(KERN_INFO "i2c-stub loaded\n");
+       if (!chip_addr) {
+               printk(KERN_ERR "i2c-stub: Please specify a chip address\n");
+               return -ENODEV;
+       }
+       if (chip_addr < 0x03 || chip_addr > 0x77) {
+               printk(KERN_ERR "i2c-stub: Invalid chip address 0x%02x\n",
+                      chip_addr);
+               return -EINVAL;
+       }
+
+       printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", chip_addr);
        return i2c_add_adapter(&stub_adapter);
 }
 
index 484bbacfce6bf005fc435f7f1a653fdc7659495f..910e200ad5001a0ee2e37c2444e0f2c58a3a5595 100644 (file)
@@ -81,7 +81,6 @@ static struct i2c_algo_bit_data bit_data = {
        .getsda         = bit_via_getsda,
        .getscl         = bit_via_getscl,
        .udelay         = 5,
-       .mdelay         = 5,
        .timeout        = HZ
 };
 
index 47e52bf2c5ec836f606e3c1a66684b1489771745..efc6bbf0cc0a49818b569208f92f92062acefaf2 100644 (file)
@@ -34,6 +34,8 @@
    VT8233A            0x3147             yes?
    VT8235             0x3177             yes
    VT8237R            0x3227             yes
+   VT8237A            0x3337             yes
+   VT8251             0x3287             yes
 
    Note: we assume there can only be one device, with one SMBus interface.
 */
@@ -297,7 +299,7 @@ static u32 vt596_func(struct i2c_adapter *adapter)
        return func;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = vt596_access,
        .functionality  = vt596_func,
 };
@@ -381,7 +383,9 @@ found:
        dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
 
        switch (pdev->device) {
+       case PCI_DEVICE_ID_VIA_8251:
        case PCI_DEVICE_ID_VIA_8237:
+       case PCI_DEVICE_ID_VIA_8237A:
        case PCI_DEVICE_ID_VIA_8235:
        case PCI_DEVICE_ID_VIA_8233A:
        case PCI_DEVICE_ID_VIA_8233_0:
@@ -432,8 +436,12 @@ static struct pci_device_id vt596_ids[] = {
          .driver_data = SMBBA3 },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
          .driver_data = SMBBA3 },
+       { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A),
+         .driver_data = SMBBA3 },
        { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
          .driver_data = SMBBA1 },
+       { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251),
+         .driver_data = SMBBA3 },
        { 0, }
 };
 
index b675773b0cc1d19a9222b87fd319027b4bfef773..6c8d25183382ed7feb150cb72d193b03af4a4f95 100644 (file)
@@ -160,7 +160,6 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = {
        .getsda         = bit_vooi2c_getsda,
        .getscl         = bit_vooi2c_getscl,
        .udelay         = CYCLE_DELAY,
-       .mdelay         = CYCLE_DELAY,
        .timeout        = TIMEOUT
 };
 
@@ -177,7 +176,6 @@ static struct i2c_algo_bit_data voo_ddc_bit_data = {
        .getsda         = bit_vooddc_getsda,
        .getscl         = bit_vooddc_getscl,
        .udelay         = CYCLE_DELAY,
-       .mdelay         = CYCLE_DELAY,
        .timeout        = TIMEOUT
 };
 
index eae9e81be375acecb2a697fd23b7afdcab944b6a..32aab0d34ee930eb3b9a6f0a95fa752c7f32b7d9 100644 (file)
@@ -383,7 +383,7 @@ static u32 scx200_acb_func(struct i2c_adapter *adapter)
 }
 
 /* For now, we only handle combined mode (smbus) */
-static struct i2c_algorithm scx200_acb_algorithm = {
+static const struct i2c_algorithm scx200_acb_algorithm = {
        .smbus_xfer     = scx200_acb_smbus_xfer,
        .functionality  = scx200_acb_func,
 };
index cb3ef5ac99fd06976c0145fd4be0399044f03b90..8b65a5cf8251f1791f389750518529f7e0e69ec6 100644 (file)
@@ -71,12 +71,12 @@ static int scx200_i2c_getsda(void *data)
  */
 
 static struct i2c_algo_bit_data scx200_i2c_data = {
-       NULL,
-       scx200_i2c_setsda,
-       scx200_i2c_setscl,
-       scx200_i2c_getsda,
-       scx200_i2c_getscl,
-       10, 10, 100,            /* waits, timeout */
+       .setsda         = scx200_i2c_setsda,
+       .setscl         = scx200_i2c_setscl,
+       .getsda         = scx200_i2c_getsda,
+       .getscl         = scx200_i2c_getscl,
+       .udelay         = 10,
+       .timeout        = 100,
 };
 
 static struct i2c_adapter scx200_i2c_ops = {
index 13c108269a6da9227f669b472b4b3e6e5ca9e4ec..cec3a0c3894dda7912024c769e04057d2a47c5ad 100644 (file)
@@ -209,10 +209,14 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* create the sysfs eeprom file */
-       sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
+       err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
+       if (err)
+               goto exit_detach;
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_kfree:
        kfree(data);
 exit:
@@ -223,6 +227,8 @@ static int eeprom_detach_client(struct i2c_client *client)
 {
        int err;
 
+       sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
+
        err = i2c_detach_client(client);
        if (err)
                return err;
index f92505b94c61fb80b2907faacbfe1419df66d05b..182f04953466080e5f443e6b091bbbd2766a23ad 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
 #include <linux/usb.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 #include <linux/i2c.h>
 #include <linux/workqueue.h>
 
index 88d2ddee449065f7db62578e41255d8a54f3ffb6..76645c1429776e182b87e3d2578adc40222cffa1 100644 (file)
@@ -199,8 +199,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
        mutex_init(&data->update_lock);
 
        /* Init fake client data */
-       /* set the client data to the i2c_client so that it will get freed */
-       i2c_set_clientdata(fake_client, fake_client);
+       i2c_set_clientdata(fake_client, NULL);
        fake_client->addr = address | 1;
        fake_client->adapter = adapter;
        fake_client->driver = &max6875_driver;
@@ -214,13 +213,17 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
                goto exit_kfree2;
 
        if ((err = i2c_attach_client(fake_client)) != 0)
-               goto exit_detach;
+               goto exit_detach1;
 
-       sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
+       err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
+       if (err)
+               goto exit_detach2;
 
        return 0;
 
-exit_detach:
+exit_detach2:
+       i2c_detach_client(fake_client);
+exit_detach1:
        i2c_detach_client(real_client);
 exit_kfree2:
        kfree(fake_client);
@@ -229,14 +232,24 @@ exit_kfree1:
        return err;
 }
 
+/* Will be called for both the real client and the fake client */
 static int max6875_detach_client(struct i2c_client *client)
 {
        int err;
+       struct max6875_data *data = i2c_get_clientdata(client);
+
+       /* data is NULL for the fake client */
+       if (data)
+               sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
 
        err = i2c_detach_client(client);
        if (err)
                return err;
-       kfree(i2c_get_clientdata(client));
+
+       if (data)               /* real client */
+               kfree(data);
+       else                    /* fake client */
+               kfree(client);
        return 0;
 }
 
index cb22280cdd277cb08c738abcc4064588413226a8..f43c4e79b55e9b3cf9bf0bba1317a0196aadddea 100644 (file)
@@ -148,11 +148,16 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
        if ((err = i2c_attach_client(new_client)))
                goto exit_kfree;
 
-       /* Register sysfs hooks (don't care about failure) */
-       sysfs_create_group(&new_client->dev.kobj, &pca9539_defattr_group);
+       /* Register sysfs hooks */
+       err = sysfs_create_group(&new_client->dev.kobj,
+                                &pca9539_defattr_group);
+       if (err)
+               goto exit_detach;
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_kfree:
        kfree(data);
 exit:
@@ -163,6 +168,8 @@ static int pca9539_detach_client(struct i2c_client *client)
 {
        int err;
 
+       sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group);
+
        if ((err = i2c_detach_client(client)))
                return err;
 
index c3e6449c4481fd1c219ed38f33c44293fa45acd1..32b25427eaba6e54ecc0a6674ab60a0a18f2c297 100644 (file)
@@ -105,6 +105,16 @@ static ssize_t set_write(struct device *dev, struct device_attribute *attr, cons
 
 static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);
 
+static struct attribute *pcf8574_attributes[] = {
+       &dev_attr_read.attr,
+       &dev_attr_write.attr,
+       NULL
+};
+
+static const struct attribute_group pcf8574_attr_group = {
+       .attrs = pcf8574_attributes,
+};
+
 /*
  * Real code
  */
@@ -166,13 +176,13 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
        pcf8574_init_client(new_client);
 
        /* Register sysfs hooks */
-       device_create_file(&new_client->dev, &dev_attr_read);
-       device_create_file(&new_client->dev, &dev_attr_write);
+       err = sysfs_create_group(&new_client->dev.kobj, &pcf8574_attr_group);
+       if (err)
+               goto exit_detach;
        return 0;
 
-/* OK, this is not exactly good programming practice, usually. But it is
-   very code-efficient in this case. */
-
+      exit_detach:
+       i2c_detach_client(new_client);
       exit_free:
        kfree(data);
       exit:
@@ -183,6 +193,8 @@ static int pcf8574_detach_client(struct i2c_client *client)
 {
        int err;
 
+       sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group);
+
        if ((err = i2c_detach_client(client)))
                return err;
 
index 925a6b371fd248651238cad2f92bb89b67dfc1c7..4dc36376eb3267f5b702b33ccdc80f0a5a7d926d 100644 (file)
@@ -158,6 +158,28 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr
 static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, 
                   show_out0_enable, set_out0_enable);
 
+static struct attribute *pcf8591_attributes[] = {
+       &dev_attr_out0_enable.attr,
+       &dev_attr_out0_output.attr,
+       &dev_attr_in0_input.attr,
+       &dev_attr_in1_input.attr,
+       NULL
+};
+
+static const struct attribute_group pcf8591_attr_group = {
+       .attrs = pcf8591_attributes,
+};
+
+static struct attribute *pcf8591_attributes_opt[] = {
+       &dev_attr_in2_input.attr,
+       &dev_attr_in3_input.attr,
+       NULL
+};
+
+static const struct attribute_group pcf8591_attr_group_opt = {
+       .attrs = pcf8591_attributes_opt,
+};
+
 /*
  * Real code
  */
@@ -211,24 +233,31 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
        pcf8591_init_client(new_client);
 
        /* Register sysfs hooks */
-       device_create_file(&new_client->dev, &dev_attr_out0_enable);
-       device_create_file(&new_client->dev, &dev_attr_out0_output);
-       device_create_file(&new_client->dev, &dev_attr_in0_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
+       err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group);
+       if (err)
+               goto exit_detach;
 
        /* Register input2 if not in "two differential inputs" mode */
-       if (input_mode != 3 )
-               device_create_file(&new_client->dev, &dev_attr_in2_input);
-               
+       if (input_mode != 3) {
+               if ((err = device_create_file(&new_client->dev,
+                                             &dev_attr_in2_input)))
+                       goto exit_sysfs_remove;
+       }
+
        /* Register input3 only in "four single ended inputs" mode */
-       if (input_mode == 0)
-               device_create_file(&new_client->dev, &dev_attr_in3_input);
-       
+       if (input_mode == 0) {
+               if ((err = device_create_file(&new_client->dev,
+                                             &dev_attr_in3_input)))
+                       goto exit_sysfs_remove;
+       }
+
        return 0;
-       
-       /* OK, this is not exactly good programming practice, usually. But it is
-          very code-efficient in this case. */
 
+exit_sysfs_remove:
+       sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt);
+       sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group);
+exit_detach:
+       i2c_detach_client(new_client);
 exit_kfree:
        kfree(data);
 exit:
@@ -239,6 +268,9 @@ static int pcf8591_detach_client(struct i2c_client *client)
 {
        int err;
 
+       sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
+       sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
+
        if ((err = i2c_detach_client(client)))
                return err;
 
index 0be6fd6a267d0ae2037966ad07d966beaca17b4c..6a7578217177ba4808f97dbbc35ebf45b68440f9 100644 (file)
@@ -305,7 +305,7 @@ static int dbg_show(struct seq_file *s, void *_)
 
 static int dbg_tps_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, dbg_show, inode->u.generic_ip);
+       return single_open(file, dbg_show, inode->i_private);
 }
 
 static struct file_operations debug_fops = {
index 9cb277d6aa48bbff97dc6582051e5ab03e912850..01233f0f7771687951a5dda8e6e2482a0bbaeca5 100644 (file)
@@ -183,15 +183,21 @@ int i2c_add_adapter(struct i2c_adapter *adap)
        sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
        adap->dev.driver = &i2c_adapter_driver;
        adap->dev.release = &i2c_adapter_dev_release;
-       device_register(&adap->dev);
-       device_create_file(&adap->dev, &dev_attr_name);
+       res = device_register(&adap->dev);
+       if (res)
+               goto out_list;
+       res = device_create_file(&adap->dev, &dev_attr_name);
+       if (res)
+               goto out_unregister;
 
        /* Add this adapter to the i2c_adapter class */
        memset(&adap->class_dev, 0x00, sizeof(struct class_device));
        adap->class_dev.dev = &adap->dev;
        adap->class_dev.class = &i2c_adapter_class;
        strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
-       class_device_register(&adap->class_dev);
+       res = class_device_register(&adap->class_dev);
+       if (res)
+               goto out_remove_name;
 
        dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
 
@@ -206,6 +212,17 @@ int i2c_add_adapter(struct i2c_adapter *adap)
 out_unlock:
        mutex_unlock(&core_lists);
        return res;
+
+out_remove_name:
+       device_remove_file(&adap->dev, &dev_attr_name);
+out_unregister:
+       init_completion(&adap->dev_released); /* Needed? */
+       device_unregister(&adap->dev);
+       wait_for_completion(&adap->dev_released);
+out_list:
+       list_del(&adap->list);
+       idr_remove(&i2c_adapter_idr, adap->nr);
+       goto out_unlock;
 }
 
 
@@ -394,14 +411,14 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
 int i2c_attach_client(struct i2c_client *client)
 {
        struct i2c_adapter *adapter = client->adapter;
+       int res = 0;
 
        mutex_lock(&adapter->clist_lock);
        if (__i2c_check_addr(client->adapter, client->addr)) {
-               mutex_unlock(&adapter->clist_lock);
-               return -EBUSY;
+               res = -EBUSY;
+               goto out_unlock;
        }
        list_add_tail(&client->list,&adapter->clients);
-       mutex_unlock(&adapter->clist_lock);
        
        if (adapter->client_register)  {
                if (adapter->client_register(client))  {
@@ -422,10 +439,26 @@ int i2c_attach_client(struct i2c_client *client)
                "%d-%04x", i2c_adapter_id(adapter), client->addr);
        dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
                client->name, client->dev.bus_id);
-       device_register(&client->dev);
-       device_create_file(&client->dev, &dev_attr_client_name);
-       
-       return 0;
+       res = device_register(&client->dev);
+       if (res)
+               goto out_list;
+       res = device_create_file(&client->dev, &dev_attr_client_name);
+       if (res)
+               goto out_unregister;
+
+out_unlock:
+       mutex_unlock(&adapter->clist_lock);
+       return res;
+
+out_unregister:
+       init_completion(&client->released); /* Needed? */
+       device_unregister(&client->dev);
+       wait_for_completion(&client->released);
+out_list:
+       list_del(&client->list);
+       dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
+               "(%d)\n", client->name, client->addr, res);
+       goto out_unlock;
 }
 
 
@@ -674,11 +707,16 @@ static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
 
        /* Finally call the custom detection function */
        err = found_proc(adapter, addr, kind);
-
        /* -ENODEV can be returned if there is a chip at the given address
           but it isn't supported by this chip driver. We catch it here as
           this isn't an error. */
-       return (err == -ENODEV) ? 0 : err;
+       if (err == -ENODEV)
+               err = 0;
+
+       if (err)
+               dev_warn(&adapter->dev, "Client creation failed at 0x%x (%d)\n",
+                        addr, err);
+       return err;
 }
 
 int i2c_probe(struct i2c_adapter *adapter,
@@ -868,7 +906,7 @@ s32 i2c_smbus_read_byte(struct i2c_client *client)
                           I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
                return -1;
        else
-               return 0x0FF & data.byte;
+               return data.byte;
 }
 
 s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
@@ -884,7 +922,7 @@ s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
                           I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
                return -1;
        else
-               return 0x0FF & data.byte;
+               return data.byte;
 }
 
 s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
@@ -903,7 +941,7 @@ s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
                           I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
                return -1;
        else
-               return 0x0FFFF & data.word;
+               return data.word;
 }
 
 s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
@@ -1006,7 +1044,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                else {
                        msg[0].len=3;
                        msgbuf0[1] = data->word & 0xff;
-                       msgbuf0[2] = (data->word >> 8) & 0xff;
+                       msgbuf0[2] = data->word >> 8;
                }
                break;
        case I2C_SMBUS_PROC_CALL:
@@ -1015,7 +1053,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                msg[0].len = 3;
                msg[1].len = 2;
                msgbuf0[1] = data->word & 0xff;
-               msgbuf0[2] = (data->word >> 8) & 0xff;
+               msgbuf0[2] = data->word >> 8;
                break;
        case I2C_SMBUS_BLOCK_DATA:
                if (read_write == I2C_SMBUS_READ) {
index 58ccddd5c237dd5823140da8857691ed9780cc9f..3f869033ed70cd212c6a99a6d54f4b615abfbed1 100644 (file)
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
-#include <linux/platform_device.h>
 #include <asm/uaccess.h>
 
-static struct i2c_client i2cdev_client_template;
+static struct i2c_driver i2cdev_driver;
 
 struct i2c_dev {
-       int minor;
+       struct list_head list;
        struct i2c_adapter *adap;
        struct class_device *class_dev;
 };
-#define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev)
 
 #define I2C_MINORS     256
-static struct i2c_dev *i2c_dev_array[I2C_MINORS];
-static DEFINE_SPINLOCK(i2c_dev_array_lock);
+static LIST_HEAD(i2c_dev_list);
+static DEFINE_SPINLOCK(i2c_dev_list_lock);
 
 static struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
 {
        struct i2c_dev *i2c_dev;
 
-       spin_lock(&i2c_dev_array_lock);
-       i2c_dev = i2c_dev_array[index];
-       spin_unlock(&i2c_dev_array_lock);
-       return i2c_dev;
-}
-
-static struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap)
-{
-       struct i2c_dev *i2c_dev = NULL;
-
-       spin_lock(&i2c_dev_array_lock);
-       if ((i2c_dev_array[adap->nr]) &&
-           (i2c_dev_array[adap->nr]->adap == adap))
-               i2c_dev = i2c_dev_array[adap->nr];
-       spin_unlock(&i2c_dev_array_lock);
+       spin_lock(&i2c_dev_list_lock);
+       list_for_each_entry(i2c_dev, &i2c_dev_list, list) {
+               if (i2c_dev->adap->nr == index)
+                       goto found;
+       }
+       i2c_dev = NULL;
+found:
+       spin_unlock(&i2c_dev_list_lock);
        return i2c_dev;
 }
 
@@ -76,30 +68,28 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
 {
        struct i2c_dev *i2c_dev;
 
+       if (adap->nr >= I2C_MINORS) {
+               printk(KERN_ERR "i2c-dev: Out of device minors (%d)\n",
+                      adap->nr);
+               return ERR_PTR(-ENODEV);
+       }
+
        i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);
        if (!i2c_dev)
                return ERR_PTR(-ENOMEM);
+       i2c_dev->adap = adap;
 
-       spin_lock(&i2c_dev_array_lock);
-       if (i2c_dev_array[adap->nr]) {
-               spin_unlock(&i2c_dev_array_lock);
-               dev_err(&adap->dev, "i2c-dev already has a device assigned to this adapter\n");
-               goto error;
-       }
-       i2c_dev->minor = adap->nr;
-       i2c_dev_array[adap->nr] = i2c_dev;
-       spin_unlock(&i2c_dev_array_lock);
+       spin_lock(&i2c_dev_list_lock);
+       list_add_tail(&i2c_dev->list, &i2c_dev_list);
+       spin_unlock(&i2c_dev_list_lock);
        return i2c_dev;
-error:
-       kfree(i2c_dev);
-       return ERR_PTR(-ENODEV);
 }
 
 static void return_i2c_dev(struct i2c_dev *i2c_dev)
 {
-       spin_lock(&i2c_dev_array_lock);
-       i2c_dev_array[i2c_dev->minor] = NULL;
-       spin_unlock(&i2c_dev_array_lock);
+       spin_lock(&i2c_dev_list_lock);
+       list_del(&i2c_dev->list);
+       spin_unlock(&i2c_dev_list_lock);
 }
 
 static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
@@ -375,12 +365,13 @@ static int i2cdev_open(struct inode *inode, struct file *file)
        if (!adap)
                return -ENODEV;
 
-       client = kmalloc(sizeof(*client), GFP_KERNEL);
+       client = kzalloc(sizeof(*client), GFP_KERNEL);
        if (!client) {
                i2c_put_adapter(adap);
                return -ENOMEM;
        }
-       memcpy(client, &i2cdev_client_template, sizeof(*client));
+       snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
+       client->driver = &i2cdev_driver;
 
        /* registered with adapter, passed as client to user */
        client->adapter = adap;
@@ -415,41 +406,47 @@ static struct class *i2c_dev_class;
 static int i2cdev_attach_adapter(struct i2c_adapter *adap)
 {
        struct i2c_dev *i2c_dev;
-       struct device *dev;
+       int res;
 
        i2c_dev = get_free_i2c_dev(adap);
        if (IS_ERR(i2c_dev))
                return PTR_ERR(i2c_dev);
 
-       pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
-                adap->name, i2c_dev->minor);
-
        /* register this i2c device with the driver core */
-       i2c_dev->adap = adap;
-       dev = &adap->dev;
        i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL,
-                                                MKDEV(I2C_MAJOR, i2c_dev->minor),
-                                                dev, "i2c-%d", i2c_dev->minor);
-       if (!i2c_dev->class_dev)
+                                                MKDEV(I2C_MAJOR, adap->nr),
+                                                &adap->dev, "i2c-%d",
+                                                adap->nr);
+       if (!i2c_dev->class_dev) {
+               res = -ENODEV;
                goto error;
-       class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
+       }
+       res = class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
+       if (res)
+               goto error_destroy;
+
+       pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
+                adap->name, adap->nr);
        return 0;
+error_destroy:
+       class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
 error:
        return_i2c_dev(i2c_dev);
        kfree(i2c_dev);
-       return -ENODEV;
+       return res;
 }
 
 static int i2cdev_detach_adapter(struct i2c_adapter *adap)
 {
        struct i2c_dev *i2c_dev;
 
-       i2c_dev = i2c_dev_get_by_adapter(adap);
-       if (!i2c_dev)
-               return -ENODEV;
+       i2c_dev = i2c_dev_get_by_minor(adap->nr);
+       if (!i2c_dev) /* attach_adapter must have failed */
+               return 0;
 
+       class_device_remove_file(i2c_dev->class_dev, &class_device_attr_name);
        return_i2c_dev(i2c_dev);
-       class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, i2c_dev->minor));
+       class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
        kfree(i2c_dev);
 
        pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
@@ -471,12 +468,6 @@ static struct i2c_driver i2cdev_driver = {
        .detach_client  = i2cdev_detach_client,
 };
 
-static struct i2c_client i2cdev_client_template = {
-       .name           = "I2C /dev entry",
-       .addr           = -1,
-       .driver         = &i2cdev_driver,
-};
-
 static int __init i2c_dev_init(void)
 {
        int res;
index defd4b4bd37488ab38198e8ab86f963c438e2809..9c8468de1a7521aa62c179cd6bf952fa461a2a4c 100644 (file)
@@ -1207,7 +1207,7 @@ int system_bus_clock (void)
 
 EXPORT_SYMBOL(system_bus_clock);
 
-static int generic_ide_suspend(struct device *dev, pm_message_t state)
+static int generic_ide_suspend(struct device *dev, pm_message_t mesg)
 {
        ide_drive_t *drive = dev->driver_data;
        struct request rq;
@@ -1221,7 +1221,9 @@ static int generic_ide_suspend(struct device *dev, pm_message_t state)
        rq.special = &args;
        rq.end_io_data = &rqpm;
        rqpm.pm_step = ide_pm_state_start_suspend;
-       rqpm.pm_state = state.event;
+       if (mesg.event == PM_EVENT_PRETHAW)
+               mesg.event = PM_EVENT_FREEZE;
+       rqpm.pm_state = mesg.event;
 
        return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
index 996c694341bc33d47971d1ef0a01c8d42adc3982..31ad79f52df72386b5b99ec334353dd8d3240e5b 100644 (file)
@@ -1369,15 +1369,16 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
 }
 
 static int
-pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t state)
+pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
 {
        ide_hwif_t      *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
        int             rc = 0;
 
-       if (state.event != mdev->ofdev.dev.power.power_state.event && state.event >= PM_EVENT_SUSPEND) {
+       if (mesg.event != mdev->ofdev.dev.power.power_state.event
+                       && mesg.event == PM_EVENT_SUSPEND) {
                rc = pmac_ide_do_suspend(hwif);
                if (rc == 0)
-                       mdev->ofdev.dev.power.power_state = state;
+                       mdev->ofdev.dev.power.power_state = mesg;
        }
 
        return rc;
@@ -1473,15 +1474,16 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 }
 
 static int
-pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
        ide_hwif_t      *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
        int             rc = 0;
        
-       if (state.event != pdev->dev.power.power_state.event && state.event >= 2) {
+       if (mesg.event != pdev->dev.power.power_state.event
+                       && mesg.event == PM_EVENT_SUSPEND) {
                rc = pmac_ide_do_suspend(hwif);
                if (rc == 0)
-                       pdev->dev.power.power_state = state;
+                       pdev->dev.power.power_state = mesg;
        }
 
        return rc;
index e6f41238f5e8c6c2f579cb5de5ae1fe0d66ce224..b4f146f2c951c9f7f2f208d8ec972d29e95f77eb 100644 (file)
@@ -137,7 +137,6 @@ static struct i2c_algo_bit_data bit_data = {
        .getsda                 = bit_getsda,
        .getscl                 = bit_getscl,
        .udelay                 = 5,
-       .mdelay                 = 5,
        .timeout                = 100,
 };
 
index 082f03c158f006825bba87446b442fc0f726eb60..493f4c65c7a2b5acaa5ca753a08bf772772d70a2 100644 (file)
@@ -2987,10 +2987,7 @@ error1:
 static void __exit ib_mad_cleanup_module(void)
 {
        ib_unregister_client(&mad_client);
-
-       if (kmem_cache_destroy(ib_mad_cache)) {
-               printk(KERN_DEBUG PFX "Failed to destroy ib_mad cache\n");
-       }
+       kmem_cache_destroy(ib_mad_cache);
 }
 
 module_init(ib_mad_init_module);
index a5eb30a06a5cb0698c2f93f44202ac3bcf76a200..c8a8af0fe47175abfe6c2f07aa36df9d0a07d2a5 100644 (file)
@@ -61,10 +61,9 @@ static int ipathfs_mknod(struct inode *dir, struct dentry *dentry,
        inode->i_mode = mode;
        inode->i_uid = 0;
        inode->i_gid = 0;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-       inode->u.generic_ip = data;
+       inode->i_private = data;
        if ((mode & S_IFMT) == S_IFDIR) {
                inode->i_op = &simple_dir_inode_operations;
                inode->i_nlink++;
@@ -119,7 +118,7 @@ static ssize_t atomic_counters_read(struct file *file, char __user *buf,
        u16 i;
        struct ipath_devdata *dd;
 
-       dd = file->f_dentry->d_inode->u.generic_ip;
+       dd = file->f_dentry->d_inode->i_private;
 
        for (i = 0; i < NUM_COUNTERS; i++)
                counters[i] = ipath_snap_cntr(dd, i);
@@ -139,7 +138,7 @@ static ssize_t atomic_node_info_read(struct file *file, char __user *buf,
        struct ipath_devdata *dd;
        u64 guid;
 
-       dd = file->f_dentry->d_inode->u.generic_ip;
+       dd = file->f_dentry->d_inode->i_private;
 
        guid = be64_to_cpu(dd->ipath_guid);
 
@@ -178,7 +177,7 @@ static ssize_t atomic_port_info_read(struct file *file, char __user *buf,
        u32 tmp, tmp2;
        struct ipath_devdata *dd;
 
-       dd = file->f_dentry->d_inode->u.generic_ip;
+       dd = file->f_dentry->d_inode->i_private;
 
        /* so we only initialize non-zero fields. */
        memset(portinfo, 0, sizeof portinfo);
@@ -325,7 +324,7 @@ static ssize_t flash_read(struct file *file, char __user *buf,
                goto bail;
        }
 
-       dd = file->f_dentry->d_inode->u.generic_ip;
+       dd = file->f_dentry->d_inode->i_private;
        if (ipath_eeprom_read(dd, pos, tmp, count)) {
                ipath_dev_err(dd, "failed to read from flash\n");
                ret = -ENXIO;
@@ -381,7 +380,7 @@ static ssize_t flash_write(struct file *file, const char __user *buf,
                goto bail_tmp;
        }
 
-       dd = file->f_dentry->d_inode->u.generic_ip;
+       dd = file->f_dentry->d_inode->i_private;
        if (ipath_eeprom_write(dd, pos, tmp, count)) {
                ret = -ENXIO;
                ipath_dev_err(dd, "failed to write to flash\n");
index bf2455a6d56238024136ba00655df965900e3561..5c9b509e40e449c24645c72b1418057a5b0d9c00 100644 (file)
@@ -742,7 +742,6 @@ static int ipath_setup_ht_reset(struct ipath_devdata *dd)
        return 0;
 }
 
-#define HT_CAPABILITY_ID   0x08        /* HT capabilities not defined in kernel */
 #define HT_INTR_DISC_CONFIG  0x80      /* HT interrupt and discovery cap */
 #define HT_INTR_REG_INDEX    2 /* intconfig requires indirect accesses */
 
@@ -973,7 +972,7 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd,
         * do this early, before we ever enable errors or hardware errors,
         * mostly to avoid causing the chip to enter freeze mode.
         */
-       pos = pci_find_capability(pdev, HT_CAPABILITY_ID);
+       pos = pci_find_capability(pdev, PCI_CAP_ID_HT);
        if (!pos) {
                ipath_dev_err(dd, "Couldn't find HyperTransport "
                              "capability; no interrupts\n");
@@ -996,7 +995,7 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd,
                else if (cap_type == HT_INTR_DISC_CONFIG)
                        ihandler = set_int_handler(dd, pdev, pos);
        } while ((pos = pci_find_next_capability(pdev, pos,
-                                                HT_CAPABILITY_ID)));
+                                                PCI_CAP_ID_HT)));
 
        if (!ihandler) {
                ipath_dev_err(dd, "Couldn't find interrupt handler in "
index 5dde380e8dbe9c2653c0014020f32ebc8e87732d..f1cb83688b318ef62d0cf6240019e23db74676f7 100644 (file)
@@ -141,7 +141,7 @@ static int ipoib_mcg_open(struct inode *inode, struct file *file)
                return ret;
 
        seq = file->private_data;
-       seq->private = inode->u.generic_ip;
+       seq->private = inode->i_private;
 
        return 0;
 }
@@ -247,7 +247,7 @@ static int ipoib_path_open(struct inode *inode, struct file *file)
                return ret;
 
        seq = file->private_data;
-       seq->private = inode->u.generic_ip;
+       seq->private = inode->i_private;
 
        return 0;
 }
index fa97e0f79e7eaaa7779a0a819ddb875251035712..ee6c2f40cdf6d6c5ca14603ace5e7d69a6e7029d 100644 (file)
@@ -15,7 +15,6 @@
 #define HP680_TS_ABS_Y_MIN     80
 #define HP680_TS_ABS_Y_MAX     910
 
-#define        SCPCR   0xa4000116
 #define        PHDR    0xa400012e
 #define SCPDR  0xa4000136
 
@@ -77,19 +76,6 @@ static irqreturn_t hp680_ts_interrupt(int irq, void *dev, struct pt_regs *regs)
 
 static int __init hp680_ts_init(void)
 {
-       u8 scpdr;
-       u16 scpcr;
-
-       scpdr = ctrl_inb(SCPDR);
-       scpdr |= SCPDR_TS_SCAN_X | SCPDR_TS_SCAN_Y;
-       scpdr &= ~SCPDR_TS_SCAN_ENABLE;
-       ctrl_outb(scpdr, SCPDR);
-
-       scpcr = ctrl_inw(SCPCR);
-       scpcr &= ~SCPCR_TS_MASK;
-       scpcr |= SCPCR_TS_ENABLE;
-       ctrl_outw(scpcr, SCPCR);
-
        hp680_ts_dev = input_allocate_device();
        if (!hp680_ts_dev)
                return -ENOMEM;
index 9ea6bd0ddc35bdcb2fc532b00a84e0760829e136..2dd1b57b0ba4959ab9578eb9de478410225e7094 100644 (file)
@@ -104,7 +104,6 @@ capifs_fill_super(struct super_block *s, void *data, int silent)
        inode->i_ino = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        inode->i_blocks = 0;
-       inode->i_blksize = 1024;
        inode->i_uid = inode->i_gid = 0;
        inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
        inode->i_op = &simple_dir_inode_operations;
@@ -149,7 +148,6 @@ void capifs_new_ncci(unsigned int number, dev_t device)
        if (!inode)
                return;
        inode->i_ino = number+2;
-       inode->i_blksize = 1024;
        inode->i_uid = config.setuid ? config.uid : current->fsuid;
        inode->i_gid = config.setgid ? config.gid : current->fsgid;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
index 3845defd49010b840f781740ddbc7d5290e15f5d..5cfbe6a380101cb2f099b83acbb124e4b09e70a2 100644 (file)
@@ -192,7 +192,7 @@ static char *get_usb_statmsg(int status)
                return "bit stuffing error, timeout, or unknown USB error";
        case -EILSEQ:
                return "CRC mismatch, timeout, or unknown USB error";
-       case -ETIMEDOUT:
+       case -ETIME:
                return "timed out";
        case -EPIPE:
                return "endpoint stalled";
index ec52c1a7c22afca97308f353e139eead2dd2b33a..6349367ed48096a93c436be1e5bfb84deb817873 100644 (file)
@@ -137,11 +137,11 @@ static struct hfcusb_symbolic_list urb_errlist[] = {
        {-ENXIO, "URB already queued"},
        {-EFBIG, "Too much ISO frames requested"},
        {-ENOSR, "Buffer error (overrun)"},
-       {-EPIPE, "Specified endpoint is stalled (device not responding)"},
+       {-EPIPE, "Specified endpoint is stalled"},
        {-EOVERFLOW, "Babble (bad cable?)"},
        {-EPROTO, "Bit-stuff error (bad cable?)"},
-       {-EILSEQ, "CRC/Timeout"},
-       {-ETIMEDOUT, "NAK (device does not respond)"},
+       {-EILSEQ, "CRC or missing token"},
+       {-ETIME, "Device did not respond"},
        {-ESHUTDOWN, "Device unplugged"},
        {-1, NULL}
 };
index 001c71b6be61a970a59aad312bf59b65ab706e54..410fa6d620ff930daa43744a54e6a53880d28cf5 100644 (file)
@@ -981,7 +981,7 @@ static int cinergyt2_suspend (struct usb_interface *intf, pm_message_t state)
        if (cinergyt2->disconnect_pending || mutex_lock_interruptible(&cinergyt2->sem))
                return -ERESTARTSYS;
 
-       if (state.event > PM_EVENT_ON) {
+       if (1) {
                struct cinergyt2 *cinergyt2 = usb_get_intfdata (intf);
 
                cinergyt2_suspend_rc(cinergyt2);
index 9002f35aa952822f7144b15bfeddf76fff08c2b8..88b283731bb8c84e1dcf7c4a90cc15b0604fd1c6 100644 (file)
@@ -80,7 +80,6 @@ static void dvb_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
 
        switch (urb->status) {
                case 0:         /* success */
-               case -ETIMEDOUT:    /* NAK */
                        break;
                case -ECONNRESET:   /* kill */
                case -ENOENT:
index 6c1cb770bcf5d28ccecd3ea2d743fc7099bea056..c9d663549dff849cff3666ed72a1c4af2e790dbf 100644 (file)
@@ -215,7 +215,7 @@ static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs)
                case -ECONNRESET:
                case -ENOENT:
                case -ESHUTDOWN:
-               case -ETIMEDOUT:
+               case -ETIME:
                        /* this urb is dead, cleanup */
                        dprintk("%s:urb shutting down with status: %d\n",
                                        __FUNCTION__, urb->status);
index 4b562b386fcf6d044882077359763bb2e84ac241..0dfbcc85ebb9d901ba36c53d509da2f794157673 100644 (file)
@@ -100,7 +100,6 @@ static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
        .getsda  = bttv_bit_getsda,
        .getscl  = bttv_bit_getscl,
        .udelay  = 16,
-       .mdelay  = 10,
        .timeout = 200,
 };
 
index 70663805cc301234efc682a4901179322b72aa1f..7bea34714861b6e3090f9319bcccfc5d4558c5d1 100644 (file)
@@ -155,7 +155,6 @@ static struct i2c_algo_bit_data cx8800_i2c_algo_template = {
        .getsda  = cx8800_bit_getsda,
        .getscl  = cx8800_bit_getscl,
        .udelay  = 16,
-       .mdelay  = 10,
        .timeout = 200,
 };
 
index 751a754a45e9c02041d29fea98a933516461d100..2b4f1970c7dfec814bf04572de62b14bc75e42e7 100644 (file)
@@ -100,7 +100,6 @@ static struct i2c_algo_bit_data vp3054_i2c_algo_template = {
        .getsda  = vp3054_bit_getsda,
        .getscl  = vp3054_bit_getscl,
        .udelay  = 16,
-       .mdelay  = 10,
        .timeout = 200,
 };
 
index 1b07a61c2ebb7dd98854e7d40dcea077189868cb..5d8cd283fcd8e747767eb5b4e7e6470be5568322 100644 (file)
@@ -301,10 +301,11 @@ static struct symbolic_list senlist[] = {
 static struct symbolic_list urb_errlist[] = {
        { -ENOSR,       "Buffer error (overrun)" },
        { -EPIPE,       "Stalled (device not responding)" },
-       { -EOVERFLOW,   "Babble (bad cable?)" },
+       { -EOVERFLOW,   "Babble (device sends too much data)" },
        { -EPROTO,      "Bit-stuff error (bad cable?)" },
-       { -EILSEQ,      "CRC/Timeout" },
-       { -ETIMEDOUT,   "NAK (device does not respond)" },
+       { -EILSEQ,      "CRC/Timeout (bad cable?)" },
+       { -ETIME,       "Device does not respond to token" },
+       { -ETIMEDOUT,   "Device does not respond to command" },
        { -1, NULL }
 };
 
index d4703944df9c12c39bb719b311da043da60cb1d9..53c4b5790d5c6dd8aa08bf132dee83c611f0ef27 100644 (file)
@@ -711,7 +711,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
                        case -EOVERFLOW:        errmsg = "Babble (bad cable?)"; break;
                        case -EPROTO:           errmsg = "Bit-stuff error (bad cable?)"; break;
                        case -EILSEQ:           errmsg = "CRC/Timeout (could be anything)"; break;
-                       case -ETIMEDOUT:        errmsg = "NAK (device does not respond)"; break;
+                       case -ETIME:            errmsg = "Device does not respond"; break;
                }
                PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
                /* Give up after a number of contiguous errors on the USB bus.
index 20f211b55ad4c4d17726c579affbfa8cccfb7e46..2912326a5aef1c6adace62d91a25bd2b8d930ea1 100644 (file)
@@ -586,15 +586,14 @@ static struct w9968cf_symbolic_list urb_errlist[] = {
        { -EFBIG,     "Too much ISO frames requested" },
        { -ENOSR,     "Buffer error (overrun)" },
        { -EPIPE,     "Specified endpoint is stalled (device not responding)"},
-       { -EOVERFLOW, "Babble (bad cable?)" },
+       { -EOVERFLOW, "Babble (too much data)" },
        { -EPROTO,    "Bit-stuff error (bad cable?)" },
        { -EILSEQ,    "CRC/Timeout" },
-       { -ETIMEDOUT, "NAK (device does not respond)" },
+       { -ETIME,     "Device does not respond to token" },
+       { -ETIMEDOUT, "Device does not respond to command" },
        { -1, NULL }
 };
 
-
-
 /****************************************************************************
  * Memory management functions                                              *
  ****************************************************************************/
index f2249ed25273bc5ded10a920e4891e587faf1c67..29f59c36f0014425ac85efbce2579316ebfff161 100644 (file)
@@ -820,7 +820,6 @@ static struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
        .getsda = zoran_i2c_getsda,
        .getscl = zoran_i2c_getscl,
        .udelay = 10,
-       .mdelay = 0,
        .timeout = 100,
 };
 
index 4a35caff5d020e0e16d0f624e648ccb8cbf5b650..b99dc507de2e4fffd7f2e19e6084cdd7b52b8694 100644 (file)
@@ -147,7 +147,6 @@ static struct inode *ibmasmfs_make_inode(struct super_block *sb, int mode)
        if (ret) {
                ret->i_mode = mode;
                ret->i_uid = ret->i_gid = 0;
-               ret->i_blksize = PAGE_CACHE_SIZE;
                ret->i_blocks = 0;
                ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
        }
@@ -175,7 +174,7 @@ static struct dentry *ibmasmfs_create_file (struct super_block *sb,
        }
 
        inode->i_fop = fops;
-       inode->u.generic_ip = data;
+       inode->i_private = data;
 
        d_add(dentry, inode);
        return dentry;
@@ -244,7 +243,7 @@ static int command_file_open(struct inode *inode, struct file *file)
 {
        struct ibmasmfs_command_data *command_data;
 
-       if (!inode->u.generic_ip)
+       if (!inode->i_private)
                return -ENODEV;
 
        command_data = kmalloc(sizeof(struct ibmasmfs_command_data), GFP_KERNEL);
@@ -252,7 +251,7 @@ static int command_file_open(struct inode *inode, struct file *file)
                return -ENOMEM;
 
        command_data->command = NULL;
-       command_data->sp = inode->u.generic_ip;
+       command_data->sp = inode->i_private;
        file->private_data = command_data;
        return 0;
 }
@@ -351,10 +350,10 @@ static int event_file_open(struct inode *inode, struct file *file)
        struct ibmasmfs_event_data *event_data;
        struct service_processor *sp; 
 
-       if (!inode->u.generic_ip)
+       if (!inode->i_private)
                return -ENODEV;
 
-       sp = inode->u.generic_ip;
+       sp = inode->i_private;
 
        event_data = kmalloc(sizeof(struct ibmasmfs_event_data), GFP_KERNEL);
        if (!event_data)
@@ -439,14 +438,14 @@ static int r_heartbeat_file_open(struct inode *inode, struct file *file)
 {
        struct ibmasmfs_heartbeat_data *rhbeat;
 
-       if (!inode->u.generic_ip)
+       if (!inode->i_private)
                return -ENODEV;
 
        rhbeat = kmalloc(sizeof(struct ibmasmfs_heartbeat_data), GFP_KERNEL);
        if (!rhbeat)
                return -ENOMEM;
 
-       rhbeat->sp = (struct service_processor *)inode->u.generic_ip;
+       rhbeat->sp = inode->i_private;
        rhbeat->active = 0;
        ibmasm_init_reverse_heartbeat(rhbeat->sp, &rhbeat->heartbeat);
        file->private_data = rhbeat;
@@ -508,7 +507,7 @@ static ssize_t r_heartbeat_file_write(struct file *file, const char __user *buf,
 
 static int remote_settings_file_open(struct inode *inode, struct file *file)
 {
-       file->private_data = inode->u.generic_ip;
+       file->private_data = inode->i_private;
        return 0;
 }
 
index 59c33925be62d2a90cba16c91f767718090bbd0f..b936373ab2a5f1e16754f7301b2cb0890fb9646d 100644 (file)
@@ -225,6 +225,7 @@ static struct eisa_device_id el3_eisa_ids[] = {
                { "TCM5095" },
                { "" }
 };
+MODULE_DEVICE_TABLE(eisa, el3_eisa_ids);
 
 static int el3_eisa_probe (struct device *device);
 
index af301f09d674223fe23299f02409290172c490aa..df42e28cc80f68808164a932c2ab8b8fda764c30 100644 (file)
@@ -851,6 +851,7 @@ static struct eisa_device_id vortex_eisa_ids[] = {
        { "TCM5970", CH_3C597 },
        { "" }
 };
+MODULE_DEVICE_TABLE(eisa, vortex_eisa_ids);
 
 static int vortex_eisa_probe(struct device *device);
 static int vortex_eisa_remove(struct device *device);
index a075246f6f438b981282f3c57752d383caf4b77c..71a4f60f7325755f7bacd457b97c3352c7f7254b 100644 (file)
@@ -163,11 +163,7 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl);
 #define SET_NETDEV_DEV(net, pdev)      do{} while(0)
 #endif
 
-#if LINUX_VERSION_CODE >= 0x2051c
 #define ace_sync_irq(irq)      synchronize_irq(irq)
-#else
-#define ace_sync_irq(irq)      synchronize_irq()
-#endif
 
 #ifndef offset_in_page
 #define offset_in_page(ptr)    ((unsigned long)(ptr) & ~PAGE_MASK)
index 6a407070c2e89bb48e2bd60d0dedf71ea796fb3e..3fb354d9c5156b6e25ab617cbcded5d4e57e74d1 100644 (file)
@@ -85,6 +85,7 @@
 #define     AD_LINK_SPEED_BITMASK_10MBPS      0x2
 #define     AD_LINK_SPEED_BITMASK_100MBPS     0x4
 #define     AD_LINK_SPEED_BITMASK_1000MBPS    0x8
+#define     AD_LINK_SPEED_BITMASK_10000MBPS   0x10
 //endalloun
 
 // compare MAC addresses
@@ -99,7 +100,7 @@ static u16 __get_link_speed(struct port *port);
 static u8 __get_duplex(struct port *port);
 static inline void __initialize_port_locks(struct port *port);
 //conversions
-static void __ntohs_lacpdu(struct lacpdu *lacpdu);
+static void __htons_lacpdu(struct lacpdu *lacpdu);
 static u16 __ad_timer_to_ticks(u16 timer_type, u16 Par);
 
 
@@ -330,7 +331,8 @@ static inline void __release_rx_machine_lock(struct port *port)
  *     0,
  *     %AD_LINK_SPEED_BITMASK_10MBPS,
  *     %AD_LINK_SPEED_BITMASK_100MBPS,
- *     %AD_LINK_SPEED_BITMASK_1000MBPS
+ *     %AD_LINK_SPEED_BITMASK_1000MBPS,
+ *     %AD_LINK_SPEED_BITMASK_10000MBPS
  */
 static u16 __get_link_speed(struct port *port)
 {
@@ -357,6 +359,10 @@ static u16 __get_link_speed(struct port *port)
                        speed = AD_LINK_SPEED_BITMASK_1000MBPS;
                        break;
 
+               case SPEED_10000:
+                       speed = AD_LINK_SPEED_BITMASK_10000MBPS;
+                       break;
+
                default:
                        speed = 0; // unknown speed value from ethtool. shouldn't happen
                        break;
@@ -414,23 +420,23 @@ static inline void __initialize_port_locks(struct port *port)
 
 //conversions
 /**
- * __ntohs_lacpdu - convert the contents of a LACPDU to host byte order
+ * __htons_lacpdu - convert the contents of a LACPDU to network byte order
  * @lacpdu: the speicifed lacpdu
  *
  * For each multi-byte field in the lacpdu, convert its content
  */
-static void __ntohs_lacpdu(struct lacpdu *lacpdu)
+static void __htons_lacpdu(struct lacpdu *lacpdu)
 {
        if (lacpdu) {
-               lacpdu->actor_system_priority =   ntohs(lacpdu->actor_system_priority);
-               lacpdu->actor_key =               ntohs(lacpdu->actor_key);
-               lacpdu->actor_port_priority =     ntohs(lacpdu->actor_port_priority);
-               lacpdu->actor_port =              ntohs(lacpdu->actor_port);
-               lacpdu->partner_system_priority = ntohs(lacpdu->partner_system_priority);
-               lacpdu->partner_key =             ntohs(lacpdu->partner_key);
-               lacpdu->partner_port_priority =   ntohs(lacpdu->partner_port_priority);
-               lacpdu->partner_port =            ntohs(lacpdu->partner_port);
-               lacpdu->collector_max_delay =     ntohs(lacpdu->collector_max_delay);
+               lacpdu->actor_system_priority =   htons(lacpdu->actor_system_priority);
+               lacpdu->actor_key =               htons(lacpdu->actor_key);
+               lacpdu->actor_port_priority =     htons(lacpdu->actor_port_priority);
+               lacpdu->actor_port =              htons(lacpdu->actor_port);
+               lacpdu->partner_system_priority = htons(lacpdu->partner_system_priority);
+               lacpdu->partner_key =             htons(lacpdu->partner_key);
+               lacpdu->partner_port_priority =   htons(lacpdu->partner_port_priority);
+               lacpdu->partner_port =            htons(lacpdu->partner_port);
+               lacpdu->collector_max_delay =     htons(lacpdu->collector_max_delay);
        }
 }
 
@@ -490,11 +496,11 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // record the new parameter values for the partner operational
-               port->partner_oper_port_number = lacpdu->actor_port;
-               port->partner_oper_port_priority = lacpdu->actor_port_priority;
+               port->partner_oper_port_number = ntohs(lacpdu->actor_port);
+               port->partner_oper_port_priority = ntohs(lacpdu->actor_port_priority);
                port->partner_oper_system = lacpdu->actor_system;
-               port->partner_oper_system_priority = lacpdu->actor_system_priority;
-               port->partner_oper_key = lacpdu->actor_key;
+               port->partner_oper_system_priority = ntohs(lacpdu->actor_system_priority);
+               port->partner_oper_key = ntohs(lacpdu->actor_key);
                // zero partener's lase states
                port->partner_oper_port_state = 0;
                port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_LACP_ACTIVITY);
@@ -561,11 +567,11 @@ static void __update_selected(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // check if any parameter is different
-               if ((lacpdu->actor_port != port->partner_oper_port_number) ||
-                   (lacpdu->actor_port_priority != port->partner_oper_port_priority) ||
+               if ((ntohs(lacpdu->actor_port) != port->partner_oper_port_number) ||
+                   (ntohs(lacpdu->actor_port_priority) != port->partner_oper_port_priority) ||
                    MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->partner_oper_system)) ||
-                   (lacpdu->actor_system_priority != port->partner_oper_system_priority) ||
-                   (lacpdu->actor_key != port->partner_oper_key) ||
+                   (ntohs(lacpdu->actor_system_priority) != port->partner_oper_system_priority) ||
+                   (ntohs(lacpdu->actor_key) != port->partner_oper_key) ||
                    ((lacpdu->actor_state & AD_STATE_AGGREGATION) != (port->partner_oper_port_state & AD_STATE_AGGREGATION))
                   ) {
                        // update the state machine Selected variable
@@ -628,11 +634,11 @@ static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // check if all parameters are alike
-               if (((lacpdu->partner_port == port->actor_port_number) &&
-                    (lacpdu->partner_port_priority == port->actor_port_priority) &&
+               if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
+                    (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
                     !MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) &&
-                    (lacpdu->partner_system_priority == port->actor_system_priority) &&
-                    (lacpdu->partner_key == port->actor_oper_port_key) &&
+                    (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
+                    (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
                     ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
                    // or this is individual link(aggregation == FALSE)
                    ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
@@ -662,11 +668,11 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
        // validate lacpdu and port
        if (lacpdu && port) {
                // check if any parameter is different
-               if ((lacpdu->partner_port != port->actor_port_number) ||
-                   (lacpdu->partner_port_priority != port->actor_port_priority) ||
+               if ((ntohs(lacpdu->partner_port) != port->actor_port_number) ||
+                   (ntohs(lacpdu->partner_port_priority) != port->actor_port_priority) ||
                    MAC_ADDRESS_COMPARE(&(lacpdu->partner_system), &(port->actor_system)) ||
-                   (lacpdu->partner_system_priority != port->actor_system_priority) ||
-                   (lacpdu->partner_key != port->actor_oper_port_key) ||
+                   (ntohs(lacpdu->partner_system_priority) != port->actor_system_priority) ||
+                   (ntohs(lacpdu->partner_key) != port->actor_oper_port_key) ||
                    ((lacpdu->partner_state & AD_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY)) ||
                    ((lacpdu->partner_state & AD_STATE_LACP_TIMEOUT) != (port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT)) ||
                    ((lacpdu->partner_state & AD_STATE_SYNCHRONIZATION) != (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) ||
@@ -775,6 +781,9 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator)
                case AD_LINK_SPEED_BITMASK_1000MBPS:
                        bandwidth = aggregator->num_of_ports * 1000;
                        break;
+               case AD_LINK_SPEED_BITMASK_10000MBPS:
+                       bandwidth = aggregator->num_of_ports * 10000;
+                       break;
                default:
                        bandwidth=0; // to silent the compilor ....
                }
@@ -847,7 +856,7 @@ static inline void __update_lacpdu_from_port(struct port *port)
         */
 
        /* Convert all non u8 parameters to Big Endian for transmit */
-       __ntohs_lacpdu(lacpdu);
+       __htons_lacpdu(lacpdu);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
@@ -2171,7 +2180,6 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
 
                switch (lacpdu->subtype) {
                case AD_TYPE_LACPDU:
-                       __ntohs_lacpdu(lacpdu);
                        dprintk("Received LACPDU on port %d\n", port->actor_port_number);
                        ad_rx_machine(lacpdu, port);
                        break;
index 850aae21a2fe4f48981ead85ee89e2f795e5227c..0fb5f653d3cebe4b41acdc4759d1934eb745542e 100644 (file)
@@ -96,6 +96,7 @@ static char *lacp_rate        = NULL;
 static char *xmit_hash_policy = NULL;
 static int arp_interval = BOND_LINK_ARP_INTERV;
 static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
+static char *arp_validate = NULL;
 struct bond_params bonding_defaults;
 
 module_param(max_bonds, int, 0);
@@ -127,6 +128,8 @@ module_param(arp_interval, int, 0);
 MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
 module_param_array(arp_ip_target, charp, NULL, 0);
 MODULE_PARM_DESC(arp_ip_target, "arp targets in n.n.n.n form");
+module_param(arp_validate, charp, 0);
+MODULE_PARM_DESC(arp_validate, "validate src/dst of ARP probes: none (default), active, backup or all");
 
 /*----------------------------- Global variables ----------------------------*/
 
@@ -170,6 +173,14 @@ struct bond_parm_tbl xmit_hashtype_tbl[] = {
 {      NULL,                   -1},
 };
 
+struct bond_parm_tbl arp_validate_tbl[] = {
+{      "none",                 BOND_ARP_VALIDATE_NONE},
+{      "active",               BOND_ARP_VALIDATE_ACTIVE},
+{      "backup",               BOND_ARP_VALIDATE_BACKUP},
+{      "all",                  BOND_ARP_VALIDATE_ALL},
+{      NULL,                   -1},
+};
+
 /*-------------------------- Forward declarations ---------------------------*/
 
 static void bond_send_gratuitous_arp(struct bonding *bond);
@@ -638,6 +649,7 @@ verify:
        case SPEED_10:
        case SPEED_100:
        case SPEED_1000:
+       case SPEED_10000:
                break;
        default:
                return -1;
@@ -1210,10 +1222,14 @@ static int bond_compute_features(struct bonding *bond)
        unsigned long features = BOND_INTERSECT_FEATURES;
        struct slave *slave;
        struct net_device *bond_dev = bond->dev;
+       unsigned short max_hard_header_len = ETH_HLEN;
        int i;
 
-       bond_for_each_slave(bond, slave, i)
+       bond_for_each_slave(bond, slave, i) {
                features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
+               if (slave->dev->hard_header_len > max_hard_header_len)
+                       max_hard_header_len = slave->dev->hard_header_len;
+       }
 
        if ((features & NETIF_F_SG) && 
            !(features & NETIF_F_ALL_CSUM))
@@ -1231,6 +1247,7 @@ static int bond_compute_features(struct bonding *bond)
 
        features |= (bond_dev->features & ~BOND_INTERSECT_FEATURES);
        bond_dev->features = features;
+       bond_dev->hard_header_len = max_hard_header_len;
 
        return 0;
 }
@@ -1365,6 +1382,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
        }
 
        new_slave->dev = slave_dev;
+       slave_dev->priv_flags |= IFF_BONDING;
 
        if ((bond->params.mode == BOND_MODE_TLB) ||
            (bond->params.mode == BOND_MODE_ALB)) {
@@ -1417,6 +1435,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        bond_compute_features(bond);
 
+       new_slave->last_arp_rx = jiffies;
+
        if (bond->params.miimon && !bond->params.use_carrier) {
                link_reporting = bond_check_dev_link(bond, slave_dev, 1);
 
@@ -1493,29 +1513,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        switch (bond->params.mode) {
        case BOND_MODE_ACTIVEBACKUP:
-               /* if we're in active-backup mode, we need one and
-                * only one active interface. The backup interfaces
-                * will have their SLAVE_INACTIVE flag set because we
-                * need them to be drop all packets. Thus, since we
-                * guarantee that curr_active_slave always point to
-                * the last usable interface, we just have to verify
-                * this interface's flag.
-                */
-               if (((!bond->curr_active_slave) ||
-                    (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) &&
-                   (new_slave->link != BOND_LINK_DOWN)) {
-                       /* first slave or no active slave yet, and this link
-                          is OK, so make this interface the active one */
-                       bond_change_active_slave(bond, new_slave);
-                       printk(KERN_INFO DRV_NAME
-                              ": %s: first active interface up!\n",
-                              bond->dev->name);
-                       netif_carrier_on(bond->dev);
-
-               } else {
-                       dprintk("This is just a backup slave\n");
-                       bond_set_slave_inactive_flags(new_slave);
-               }
+               bond_set_slave_inactive_flags(new_slave);
+               bond_select_active_slave(bond);
                break;
        case BOND_MODE_8023AD:
                /* in 802.3ad mode, the internal mechanism
@@ -1778,7 +1777,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
        dev_set_mac_address(slave_dev, &addr);
 
        slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
-                                  IFF_SLAVE_INACTIVE);
+                                  IFF_SLAVE_INACTIVE | IFF_BONDING |
+                                  IFF_SLAVE_NEEDARP);
 
        kfree(slave);
 
@@ -2291,6 +2291,25 @@ static int bond_has_ip(struct bonding *bond)
        return 0;
 }
 
+static int bond_has_this_ip(struct bonding *bond, u32 ip)
+{
+       struct vlan_entry *vlan, *vlan_next;
+
+       if (ip == bond->master_ip)
+               return 1;
+
+       if (list_empty(&bond->vlan_list))
+               return 0;
+
+       list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
+                                vlan_list) {
+               if (ip == vlan->vlan_ip)
+                       return 1;
+       }
+
+       return 0;
+}
+
 /*
  * We go to the (large) trouble of VLAN tagging ARP frames because
  * switches in VLAN mode (especially if ports are configured as
@@ -2429,6 +2448,93 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
        }
 }
 
+static void bond_validate_arp(struct bonding *bond, struct slave *slave, u32 sip, u32 tip)
+{
+       int i;
+       u32 *targets = bond->params.arp_targets;
+
+       targets = bond->params.arp_targets;
+       for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
+               dprintk("bva: sip %u.%u.%u.%u tip %u.%u.%u.%u t[%d] "
+                       "%u.%u.%u.%u bhti(tip) %d\n",
+                      NIPQUAD(sip), NIPQUAD(tip), i, NIPQUAD(targets[i]),
+                      bond_has_this_ip(bond, tip));
+               if (sip == targets[i]) {
+                       if (bond_has_this_ip(bond, tip))
+                               slave->last_arp_rx = jiffies;
+                       return;
+               }
+       }
+}
+
+static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
+{
+       struct arphdr *arp;
+       struct slave *slave;
+       struct bonding *bond;
+       unsigned char *arp_ptr;
+       u32 sip, tip;
+
+       if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
+               goto out;
+
+       bond = dev->priv;
+       read_lock(&bond->lock);
+
+       dprintk("bond_arp_rcv: bond %s skb->dev %s orig_dev %s\n",
+               bond->dev->name, skb->dev ? skb->dev->name : "NULL",
+               orig_dev ? orig_dev->name : "NULL");
+
+       slave = bond_get_slave_by_dev(bond, orig_dev);
+       if (!slave || !slave_do_arp_validate(bond, slave))
+               goto out_unlock;
+
+       /* ARP header, plus 2 device addresses, plus 2 IP addresses.  */
+       if (!pskb_may_pull(skb, (sizeof(struct arphdr) +
+                                (2 * dev->addr_len) +
+                                (2 * sizeof(u32)))))
+               goto out_unlock;
+
+       arp = skb->nh.arph;
+       if (arp->ar_hln != dev->addr_len ||
+           skb->pkt_type == PACKET_OTHERHOST ||
+           skb->pkt_type == PACKET_LOOPBACK ||
+           arp->ar_hrd != htons(ARPHRD_ETHER) ||
+           arp->ar_pro != htons(ETH_P_IP) ||
+           arp->ar_pln != 4)
+               goto out_unlock;
+
+       arp_ptr = (unsigned char *)(arp + 1);
+       arp_ptr += dev->addr_len;
+       memcpy(&sip, arp_ptr, 4);
+       arp_ptr += 4 + dev->addr_len;
+       memcpy(&tip, arp_ptr, 4);
+
+       dprintk("bond_arp_rcv: %s %s/%d av %d sv %d sip %u.%u.%u.%u"
+               " tip %u.%u.%u.%u\n", bond->dev->name, slave->dev->name,
+               slave->state, bond->params.arp_validate,
+               slave_do_arp_validate(bond, slave), NIPQUAD(sip), NIPQUAD(tip));
+
+       /*
+        * Backup slaves won't see the ARP reply, but do come through
+        * here for each ARP probe (so we swap the sip/tip to validate
+        * the probe).  In a "redundant switch, common router" type of
+        * configuration, the ARP probe will (hopefully) travel from
+        * the active, through one switch, the router, then the other
+        * switch before reaching the backup.
+        */
+       if (slave->state == BOND_STATE_ACTIVE)
+               bond_validate_arp(bond, slave, sip, tip);
+       else
+               bond_validate_arp(bond, slave, tip, sip);
+
+out_unlock:
+       read_unlock(&bond->lock);
+out:
+       dev_kfree_skb(skb);
+       return NET_RX_SUCCESS;
+}
+
 /*
  * this function is called regularly to monitor each slave's link
  * ensuring that traffic is being sent and received when arp monitoring
@@ -2593,7 +2699,8 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
         */
        bond_for_each_slave(bond, slave, i) {
                if (slave->link != BOND_LINK_UP) {
-                       if ((jiffies - slave->dev->last_rx) <= delta_in_ticks) {
+                       if ((jiffies - slave_last_rx(bond, slave)) <=
+                            delta_in_ticks) {
 
                                slave->link = BOND_LINK_UP;
 
@@ -2638,7 +2745,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
 
                        if ((slave != bond->curr_active_slave) &&
                            (!bond->current_arp_slave) &&
-                           (((jiffies - slave->dev->last_rx) >= 3*delta_in_ticks) &&
+                           (((jiffies - slave_last_rx(bond, slave)) >= 3*delta_in_ticks) &&
                             bond_has_ip(bond))) {
                                /* a backup slave has gone down; three times
                                 * the delta allows the current slave to be
@@ -2685,7 +2792,7 @@ void bond_activebackup_arp_mon(struct net_device *bond_dev)
                 * if it is up and needs to take over as the curr_active_slave
                 */
                if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) ||
-           (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) &&
+           (((jiffies - slave_last_rx(bond, slave)) >= (2*delta_in_ticks)) &&
             bond_has_ip(bond))) &&
                    ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) {
 
@@ -2950,7 +3057,7 @@ static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave
        seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
        seq_printf(seq, "MII Status: %s\n",
                   (slave->link == BOND_LINK_UP) ?  "up" : "down");
-       seq_printf(seq, "Link Failure Count: %d\n",
+       seq_printf(seq, "Link Failure Count: %u\n",
                   slave->link_failure_count);
 
        seq_printf(seq,
@@ -3210,6 +3317,9 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
                (event_dev ? event_dev->name : "None"),
                event);
 
+       if (!(event_dev->priv_flags & IFF_BONDING))
+               return NOTIFY_DONE;
+
        if (event_dev->flags & IFF_MASTER) {
                dprintk("IFF_MASTER\n");
                return bond_master_netdev_event(event, event_dev);
@@ -3305,6 +3415,21 @@ static void bond_unregister_lacpdu(struct bonding *bond)
        dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type));
 }
 
+void bond_register_arp(struct bonding *bond)
+{
+       struct packet_type *pt = &bond->arp_mon_pt;
+
+       pt->type = htons(ETH_P_ARP);
+       pt->dev = NULL; /*bond->dev;XXX*/
+       pt->func = bond_arp_rcv;
+       dev_add_pack(pt);
+}
+
+void bond_unregister_arp(struct bonding *bond)
+{
+       dev_remove_pack(&bond->arp_mon_pt);
+}
+
 /*---------------------------- Hashing Policies -----------------------------*/
 
 /*
@@ -3391,6 +3516,9 @@ static int bond_open(struct net_device *bond_dev)
                } else {
                        arp_timer->function = (void *)&bond_loadbalance_arp_mon;
                }
+               if (bond->params.arp_validate)
+                       bond_register_arp(bond);
+
                add_timer(arp_timer);
        }
 
@@ -3418,9 +3546,11 @@ static int bond_close(struct net_device *bond_dev)
                bond_unregister_lacpdu(bond);
        }
 
+       if (bond->params.arp_validate)
+               bond_unregister_arp(bond);
+
        write_lock_bh(&bond->lock);
 
-       bond_mc_list_destroy(bond);
 
        /* signal timers not to re-arm */
        bond->kill_timers = 1;
@@ -3451,8 +3581,6 @@ static int bond_close(struct net_device *bond_dev)
                break;
        }
 
-       /* Release the bonded slaves */
-       bond_release_all(bond_dev);
 
        if ((bond->params.mode == BOND_MODE_TLB) ||
            (bond->params.mode == BOND_MODE_ALB)) {
@@ -4179,6 +4307,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
        /* Initialize the device options */
        bond_dev->tx_queue_len = 0;
        bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
+       bond_dev->priv_flags |= IFF_BONDING;
 
        /* At first, we block adding VLANs. That's the only way to
         * prevent problems that occur when adding VLANs over an
@@ -4237,6 +4366,9 @@ static void bond_free_all(void)
        list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) {
                struct net_device *bond_dev = bond->dev;
 
+               bond_mc_list_destroy(bond);
+               /* Release the bonded slaves */
+               bond_release_all(bond_dev);
                unregister_netdevice(bond_dev);
                bond_deinit(bond_dev);
        }
@@ -4270,6 +4402,8 @@ int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
 
 static int bond_check_params(struct bond_params *params)
 {
+       int arp_validate_value;
+
        /*
         * Convert string parameters.
         */
@@ -4473,6 +4607,29 @@ static int bond_check_params(struct bond_params *params)
                arp_interval = 0;
        }
 
+       if (arp_validate) {
+               if (bond_mode != BOND_MODE_ACTIVEBACKUP) {
+                       printk(KERN_ERR DRV_NAME
+              ": arp_validate only supported in active-backup mode\n");
+                       return -EINVAL;
+               }
+               if (!arp_interval) {
+                       printk(KERN_ERR DRV_NAME
+                              ": arp_validate requires arp_interval\n");
+                       return -EINVAL;
+               }
+
+               arp_validate_value = bond_parse_parm(arp_validate,
+                                                    arp_validate_tbl);
+               if (arp_validate_value == -1) {
+                       printk(KERN_ERR DRV_NAME
+                              ": Error: invalid arp_validate \"%s\"\n",
+                              arp_validate == NULL ? "NULL" : arp_validate);
+                       return -EINVAL;
+               }
+       } else
+               arp_validate_value = 0;
+
        if (miimon) {
                printk(KERN_INFO DRV_NAME
                       ": MII link monitoring set to %d ms\n",
@@ -4481,8 +4638,10 @@ static int bond_check_params(struct bond_params *params)
                int i;
 
                printk(KERN_INFO DRV_NAME
-                      ": ARP monitoring set to %d ms with %d target(s):",
-                      arp_interval, arp_ip_count);
+                      ": ARP monitoring set to %d ms, validate %s, with %d target(s):",
+                      arp_interval,
+                      arp_validate_tbl[arp_validate_value].modename,
+                      arp_ip_count);
 
                for (i = 0; i < arp_ip_count; i++)
                        printk (" %s", arp_ip_target[i]);
@@ -4516,6 +4675,7 @@ static int bond_check_params(struct bond_params *params)
        params->xmit_policy = xmit_hashtype;
        params->miimon = miimon;
        params->arp_interval = arp_interval;
+       params->arp_validate = arp_validate_value;
        params->updelay = updelay;
        params->downdelay = downdelay;
        params->use_carrier = use_carrier;
index cfe4dc3a93a3b8c1264ee03dd4516f3aa44dfbd4..ced9ed8f995a45e00f657d085f8f2fce30a16c98 100644 (file)
@@ -51,6 +51,7 @@ extern struct bond_params bonding_defaults;
 extern struct bond_parm_tbl bond_mode_tbl[];
 extern struct bond_parm_tbl bond_lacp_tbl[];
 extern struct bond_parm_tbl xmit_hashtype_tbl[];
+extern struct bond_parm_tbl arp_validate_tbl[];
 
 static int expected_refcount = -1;
 static struct class *netdev_class;
@@ -502,6 +503,53 @@ out:
 }
 static CLASS_DEVICE_ATTR(xmit_hash_policy, S_IRUGO | S_IWUSR, bonding_show_xmit_hash, bonding_store_xmit_hash);
 
+/*
+ * Show and set arp_validate.
+ */
+static ssize_t bonding_show_arp_validate(struct class_device *cd, char *buf)
+{
+       struct bonding *bond = to_bond(cd);
+
+       return sprintf(buf, "%s %d\n",
+                      arp_validate_tbl[bond->params.arp_validate].modename,
+                      bond->params.arp_validate) + 1;
+}
+
+static ssize_t bonding_store_arp_validate(struct class_device *cd, const char *buf, size_t count)
+{
+       int new_value;
+       struct bonding *bond = to_bond(cd);
+
+       new_value = bond_parse_parm((char *)buf, arp_validate_tbl);
+       if (new_value < 0) {
+               printk(KERN_ERR DRV_NAME
+                      ": %s: Ignoring invalid arp_validate value %s\n",
+                      bond->dev->name, buf);
+               return -EINVAL;
+       }
+       if (new_value && (bond->params.mode != BOND_MODE_ACTIVEBACKUP)) {
+               printk(KERN_ERR DRV_NAME
+                      ": %s: arp_validate only supported in active-backup mode.\n",
+                      bond->dev->name);
+               return -EINVAL;
+       }
+       printk(KERN_INFO DRV_NAME ": %s: setting arp_validate to %s (%d).\n",
+              bond->dev->name, arp_validate_tbl[new_value].modename,
+              new_value);
+
+       if (!bond->params.arp_validate && new_value) {
+               bond_register_arp(bond);
+       } else if (bond->params.arp_validate && !new_value) {
+               bond_unregister_arp(bond);
+       }
+
+       bond->params.arp_validate = new_value;
+
+       return count;
+}
+
+static CLASS_DEVICE_ATTR(arp_validate, S_IRUGO | S_IWUSR, bonding_show_arp_validate, bonding_store_arp_validate);
+
 /*
  * Show and set the arp timer interval.  There are two tricky bits
  * here.  First, if ARP monitoring is activated, then we must disable
@@ -914,6 +962,11 @@ static ssize_t bonding_store_miimon(struct class_device *cd, const char *buf, si
                               "ARP monitoring. Disabling ARP monitoring...\n",
                               bond->dev->name);
                        bond->params.arp_interval = 0;
+                       if (bond->params.arp_validate) {
+                               bond_unregister_arp(bond);
+                               bond->params.arp_validate =
+                                       BOND_ARP_VALIDATE_NONE;
+                       }
                        /* Kill ARP timer, else it brings bond's link down */
                        if (bond->mii_timer.function) {
                                printk(KERN_INFO DRV_NAME
@@ -1093,7 +1146,7 @@ static ssize_t bonding_store_active_slave(struct class_device *cd, const char *b
                             strlen(slave->dev->name)) == 0) {
                                old_active = bond->curr_active_slave;
                                new_active = slave;
-                               if (new_active && (new_active == old_active)) {
+                               if (new_active == old_active) {
                                        /* do nothing */
                                        printk(KERN_INFO DRV_NAME
                                               ": %s: %s is already the current active slave.\n",
@@ -1273,6 +1326,7 @@ static CLASS_DEVICE_ATTR(ad_partner_mac, S_IRUGO, bonding_show_ad_partner_mac, N
 static struct attribute *per_bond_attrs[] = {
        &class_device_attr_slaves.attr,
        &class_device_attr_mode.attr,
+       &class_device_attr_arp_validate.attr,
        &class_device_attr_arp_interval.attr,
        &class_device_attr_arp_ip_target.attr,
        &class_device_attr_downdelay.attr,
index 0bdfe2c714539dd9051d8e721914aa4a612b3b79..dc434fb6da85985def44a225789359a6b076a390 100644 (file)
@@ -22,8 +22,8 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION    "3.0.3"
-#define DRV_RELDATE    "March 23, 2006"
+#define DRV_VERSION    "3.1.1"
+#define DRV_RELDATE    "September 26, 2006"
 #define DRV_NAME       "bonding"
 #define DRV_DESCRIPTION        "Ethernet Channel Bonding Driver"
 
@@ -126,6 +126,7 @@ struct bond_params {
        int xmit_policy;
        int miimon;
        int arp_interval;
+       int arp_validate;
        int use_carrier;
        int updelay;
        int downdelay;
@@ -149,8 +150,9 @@ struct slave {
        struct net_device *dev; /* first - useful for panic debug */
        struct slave *next;
        struct slave *prev;
-       s16    delay;
+       int    delay;
        u32    jiffies;
+       u32    last_arp_rx;
        s8     link;    /* one of BOND_LINK_XXXX */
        s8     state;   /* one of BOND_STATE_XXXX */
        u32    original_flags;
@@ -198,6 +200,7 @@ struct bonding {
        struct   bond_params params;
        struct   list_head vlan_list;
        struct   vlan_group *vlgrp;
+       struct   packet_type arp_mon_pt;
 };
 
 /**
@@ -228,6 +231,25 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
        return (struct bonding *)slave->dev->master->priv;
 }
 
+#define BOND_ARP_VALIDATE_NONE         0
+#define BOND_ARP_VALIDATE_ACTIVE       (1 << BOND_STATE_ACTIVE)
+#define BOND_ARP_VALIDATE_BACKUP       (1 << BOND_STATE_BACKUP)
+#define BOND_ARP_VALIDATE_ALL          (BOND_ARP_VALIDATE_ACTIVE | \
+                                        BOND_ARP_VALIDATE_BACKUP)
+
+extern inline int slave_do_arp_validate(struct bonding *bond, struct slave *slave)
+{
+       return bond->params.arp_validate & (1 << slave->state);
+}
+
+extern inline u32 slave_last_rx(struct bonding *bond, struct slave *slave)
+{
+       if (slave_do_arp_validate(bond, slave))
+               return slave->last_arp_rx;
+
+       return slave->dev->last_rx;
+}
+
 static inline void bond_set_slave_inactive_flags(struct slave *slave)
 {
        struct bonding *bond = slave->dev->master->priv;
@@ -235,12 +257,14 @@ static inline void bond_set_slave_inactive_flags(struct slave *slave)
            bond->params.mode != BOND_MODE_ALB)
                slave->state = BOND_STATE_BACKUP;
        slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
+       if (slave_do_arp_validate(bond, slave))
+               slave->dev->priv_flags |= IFF_SLAVE_NEEDARP;
 }
 
 static inline void bond_set_slave_active_flags(struct slave *slave)
 {
        slave->state = BOND_STATE_ACTIVE;
-       slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE;
+       slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP);
 }
 
 static inline void bond_set_master_3ad_flags(struct bonding *bond)
@@ -284,6 +308,8 @@ int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl);
 const char *bond_mode_name(int mode);
 void bond_select_active_slave(struct bonding *bond);
 void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
+void bond_register_arp(struct bonding *);
+void bond_unregister_arp(struct bonding *);
 
 #endif /* _LINUX_BONDING_H */
 
index a170e96251f60ce59401ff1fa53519ed650e9dca..4020acb5500580d6e4a356f788ddbcdb40243b11 100644 (file)
@@ -1367,8 +1367,8 @@ struct e1000_hw_stats {
 
 /* Structure containing variables used by the shared code (e1000_hw.c) */
 struct e1000_hw {
-    uint8_t *hw_addr;
-    uint8_t *flash_address;
+    uint8_t __iomem *hw_addr;
+    uint8_t __iomem *flash_address;
     e1000_mac_type mac_type;
     e1000_phy_type phy_type;
     uint32_t phy_init_script;
index 97db910fbc8c13d52a07d3a517079815e035f201..eea1d66c530e1e32a5a4468779b8f39588542127 100644 (file)
@@ -3789,6 +3789,12 @@ static int nv_loopback_test(struct net_device *dev)
        /* setup packet for tx */
        pkt_len = ETH_DATA_LEN;
        tx_skb = dev_alloc_skb(pkt_len);
+       if (!tx_skb) {
+               printk(KERN_ERR "dev_alloc_skb() failed during loopback test"
+                        " of %s\n", dev->name);
+               ret = 0;
+               goto out;
+       }
        pkt_data = skb_put(tx_skb, pkt_len);
        for (i = 0; i < pkt_len; i++)
                pkt_data[i] = (u8)(i & 0xff);
@@ -3853,7 +3859,7 @@ static int nv_loopback_test(struct net_device *dev)
                       tx_skb->end-tx_skb->data,
                       PCI_DMA_TODEVICE);
        dev_kfree_skb_any(tx_skb);
-
+ out:
        /* stop engines */
        nv_stop_rx(dev);
        nv_stop_tx(dev);
diff --git a/drivers/net/gt64240eth.h b/drivers/net/gt64240eth.h
deleted file mode 100644 (file)
index 0d6f486..0000000
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 Patton Electronics Company
- * Copyright (C) 2002 Momentum Computer
- *
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             stevel@mvista.com or support@mvista.com
- *
- *  This program is free software; you can distribute 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 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.
- *
- * Ethernet driver definitions for the MIPS GT96100 Advanced
- * Communication Controller.
- *
- * Modified for the Marvellous GT64240 Retarded Communication Controller.
- */
-#ifndef _GT64240ETH_H
-#define _GT64240ETH_H
-
-#include <asm/gt64240.h>
-
-#define ETHERNET_PORTS_DIFFERENCE_OFFSETS      0x400
-
-/* Translate those weanie names from Galileo/VxWorks header files: */
-
-#define GT64240_MRR                    MAIN_ROUTING_REGISTER
-#define GT64240_CIU_ARBITER_CONFIG     COMM_UNIT_ARBITER_CONFIGURATION_REGISTER
-#define GT64240_CIU_ARBITER_CONTROL    COMM_UNIT_ARBITER_CONTROL
-#define GT64240_MAIN_LOW_CAUSE         LOW_INTERRUPT_CAUSE_REGISTER
-#define GT64240_MAIN_HIGH_CAUSE        HIGH_INTERRUPT_CAUSE_REGISTER
-#define GT64240_CPU_LOW_MASK           CPU_INTERRUPT_MASK_REGISTER_LOW
-#define GT64240_CPU_HIGH_MASK          CPU_INTERRUPT_MASK_REGISTER_HIGH
-#define GT64240_CPU_SELECT_CAUSE       CPU_SELECT_CAUSE_REGISTER
-
-#define GT64240_ETH_PHY_ADDR_REG       ETHERNET_PHY_ADDRESS_REGISTER
-#define GT64240_ETH_PORT_CONFIG        ETHERNET0_PORT_CONFIGURATION_REGISTER
-#define GT64240_ETH_PORT_CONFIG_EXT    ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER
-#define GT64240_ETH_PORT_COMMAND       ETHERNET0_PORT_COMMAND_REGISTER
-#define GT64240_ETH_PORT_STATUS        ETHERNET0_PORT_STATUS_REGISTER
-#define GT64240_ETH_IO_SIZE            ETHERNET_PORTS_DIFFERENCE_OFFSETS
-#define GT64240_ETH_SMI_REG            ETHERNET_SMI_REGISTER
-#define GT64240_ETH_MIB_COUNT_BASE     ETHERNET0_MIB_COUNTER_BASE
-#define GT64240_ETH_SDMA_CONFIG        ETHERNET0_SDMA_CONFIGURATION_REGISTER
-#define GT64240_ETH_SDMA_COMM          ETHERNET0_SDMA_COMMAND_REGISTER
-#define GT64240_ETH_INT_MASK           ETHERNET0_INTERRUPT_MASK_REGISTER
-#define GT64240_ETH_INT_CAUSE          ETHERNET0_INTERRUPT_CAUSE_REGISTER
-#define GT64240_ETH_CURR_TX_DESC_PTR0  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_CURR_TX_DESC_PTR1  ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER1
-#define GT64240_ETH_1ST_RX_DESC_PTR0   ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_CURR_RX_DESC_PTR0  ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0
-#define GT64240_ETH_HASH_TBL_PTR       ETHERNET0_HASH_TABLE_POINTER_REGISTER
-
-/* Turn on NAPI by default */
-
-#define        GT64240_NAPI                    1
-
-/* Some 64240 settings that SHOULD eventually be setup in PROM monitor: */
-/* (Board-specific to the DSL3224 Rev A board ONLY!)                    */
-#define D3224_MPP_CTRL0_SETTING                0x66669900
-#define D3224_MPP_CTRL1_SETTING                0x00000000
-#define D3224_MPP_CTRL2_SETTING                0x00887700
-#define D3224_MPP_CTRL3_SETTING                0x00000044
-#define D3224_GPP_IO_CTRL_SETTING      0x0000e800
-#define D3224_GPP_LEVEL_CTRL_SETTING   0xf001f703
-#define D3224_GPP_VALUE_SETTING                0x00000000
-
-/* Keep the ring sizes a power of two for efficiency. */
-//-#define TX_RING_SIZE 16
-#define TX_RING_SIZE   64      /* TESTING !!! */
-#define RX_RING_SIZE   32
-#define PKT_BUF_SZ     1536    /* Size of each temporary Rx buffer. */
-
-#define RX_HASH_TABLE_SIZE 16384
-#define HASH_HOP_NUMBER 12
-
-#define NUM_INTERFACES 3
-
-#define GT64240ETH_TX_TIMEOUT HZ/4
-
-#define MIPS_GT64240_BASE 0xf4000000
-#define GT64240_ETH0_BASE (MIPS_GT64240_BASE + GT64240_ETH_PORT_CONFIG)
-#define GT64240_ETH1_BASE (GT64240_ETH0_BASE + GT64240_ETH_IO_SIZE)
-#define GT64240_ETH2_BASE (GT64240_ETH1_BASE + GT64240_ETH_IO_SIZE)
-
-#if defined(CONFIG_MIPS_DSL3224)
-#define GT64240_ETHER0_IRQ 4
-#define GT64240_ETHER1_IRQ 4
-#else
-#define GT64240_ETHER0_IRQ -1
-#define GT64240_ETHER1_IRQ -1
-#endif
-
-#define REV_GT64240  0x1
-#define REV_GT64240A 0x10
-
-#define GT64240ETH_READ(gp, offset)                                    \
-       GT_READ((gp)->port_offset + (offset))
-
-#define GT64240ETH_WRITE(gp, offset, data)                             \
-       GT_WRITE((gp)->port_offset + (offset), (data))
-
-#define GT64240ETH_SETBIT(gp, offset, bits)                            \
-       GT64240ETH_WRITE((gp), (offset),                                \
-                        GT64240ETH_READ((gp), (offset)) | (bits))
-
-#define GT64240ETH_CLRBIT(gp, offset, bits)                            \
-       GT64240ETH_WRITE((gp), (offset),                                \
-                        GT64240ETH_READ((gp), (offset)) & ~(bits))
-
-#define GT64240_READ(ofs)              GT_READ(ofs)
-#define GT64240_WRITE(ofs, data)       GT_WRITE((ofs), (data))
-
-/* Bit definitions of the SMI Reg */
-enum {
-       smirDataMask = 0xffff,
-       smirPhyAdMask = 0x1f << 16,
-       smirPhyAdBit = 16,
-       smirRegAdMask = 0x1f << 21,
-       smirRegAdBit = 21,
-       smirOpCode = 1 << 26,
-       smirReadValid = 1 << 27,
-       smirBusy = 1 << 28
-};
-
-/* Bit definitions of the Port Config Reg */
-enum pcr_bits {
-       pcrPM = 1 << 0,
-       pcrRBM = 1 << 1,
-       pcrPBF = 1 << 2,
-       pcrEN = 1 << 7,
-       pcrLPBKMask = 0x3 << 8,
-       pcrLPBKBit = 1 << 8,
-       pcrFC = 1 << 10,
-       pcrHS = 1 << 12,
-       pcrHM = 1 << 13,
-       pcrHDM = 1 << 14,
-       pcrHD = 1 << 15,
-       pcrISLMask = 0x7 << 28,
-       pcrISLBit = 28,
-       pcrACCS = 1 << 31
-};
-
-/* Bit definitions of the Port Config Extend Reg */
-enum pcxr_bits {
-       pcxrIGMP = 1,
-       pcxrSPAN = 2,
-       pcxrPAR = 4,
-       pcxrPRIOtxMask = 0x7 << 3,
-       pcxrPRIOtxBit = 3,
-       pcxrPRIOrxMask = 0x3 << 6,
-       pcxrPRIOrxBit = 6,
-       pcxrPRIOrxOverride = 1 << 8,
-       pcxrDPLXen = 1 << 9,
-       pcxrFCTLen = 1 << 10,
-       pcxrFLP = 1 << 11,
-       pcxrFCTL = 1 << 12,
-       pcxrMFLMask = 0x3 << 14,
-       pcxrMFLBit = 14,
-       pcxrMIBclrMode = 1 << 16,
-       pcxrSpeed = 1 << 18,
-       pcxrSpeeden = 1 << 19,
-       pcxrRMIIen = 1 << 20,
-       pcxrDSCPen = 1 << 21
-};
-
-/* Bit definitions of the Port Command Reg */
-enum pcmr_bits {
-       pcmrFJ = 1 << 15
-};
-
-
-/* Bit definitions of the Port Status Reg */
-enum psr_bits {
-       psrSpeed = 1,
-       psrDuplex = 2,
-       psrFctl = 4,
-       psrLink = 8,
-       psrPause = 1 << 4,
-       psrTxLow = 1 << 5,
-       psrTxHigh = 1 << 6,
-       psrTxInProg = 1 << 7
-};
-
-/* Bit definitions of the SDMA Config Reg */
-enum sdcr_bits {
-       sdcrRCMask = 0xf << 2,
-       sdcrRCBit = 2,
-       sdcrBLMR = 1 << 6,
-       sdcrBLMT = 1 << 7,
-       sdcrPOVR = 1 << 8,
-       sdcrRIFB = 1 << 9,
-       sdcrBSZMask = 0x3 << 12,
-       sdcrBSZBit = 12
-};
-
-/* Bit definitions of the SDMA Command Reg */
-enum sdcmr_bits {
-       sdcmrERD = 1 << 7,
-       sdcmrAR = 1 << 15,
-       sdcmrSTDH = 1 << 16,
-       sdcmrSTDL = 1 << 17,
-       sdcmrTXDH = 1 << 23,
-       sdcmrTXDL = 1 << 24,
-       sdcmrAT = 1 << 31
-};
-
-/* Bit definitions of the Interrupt Cause Reg */
-enum icr_bits {
-       icrRxBuffer = 1,
-       icrTxBufferHigh = 1 << 2,
-       icrTxBufferLow = 1 << 3,
-       icrTxEndHigh = 1 << 6,
-       icrTxEndLow = 1 << 7,
-       icrRxError = 1 << 8,
-       icrTxErrorHigh = 1 << 10,
-       icrTxErrorLow = 1 << 11,
-       icrRxOVR = 1 << 12,
-       icrTxUdr = 1 << 13,
-       icrRxBufferQ0 = 1 << 16,
-       icrRxBufferQ1 = 1 << 17,
-       icrRxBufferQ2 = 1 << 18,
-       icrRxBufferQ3 = 1 << 19,
-       icrRxErrorQ0 = 1 << 20,
-       icrRxErrorQ1 = 1 << 21,
-       icrRxErrorQ2 = 1 << 22,
-       icrRxErrorQ3 = 1 << 23,
-       icrMIIPhySTC = 1 << 28,
-       icrSMIdone = 1 << 29,
-       icrEtherIntSum = 1 << 31
-};
-
-
-/* The Rx and Tx descriptor lists. */
-#ifdef __LITTLE_ENDIAN
-typedef struct {
-       u32 cmdstat;
-       u16 reserved;           //-prk21aug01    u32 reserved:16;
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u32 buff_ptr;
-       u32 next;
-} gt64240_td_t;
-
-typedef struct {
-       u32 cmdstat;
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u16 buff_sz;            //-prk21aug01    u32 buff_sz:16;
-       u32 buff_ptr;
-       u32 next;
-} gt64240_rd_t;
-#elif defined(__BIG_ENDIAN)
-typedef struct {
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u16 reserved;           //-prk21aug01    u32 reserved:16;
-       u32 cmdstat;
-       u32 next;
-       u32 buff_ptr;
-} gt64240_td_t;
-
-typedef struct {
-       u16 buff_sz;            //-prk21aug01    u32 buff_sz:16;
-       u16 byte_cnt;           //-prk21aug01    u32 byte_cnt:16;
-       u32 cmdstat;
-       u32 next;
-       u32 buff_ptr;
-} gt64240_rd_t;
-#else
-#error Either __BIG_ENDIAN or __LITTLE_ENDIAN must be defined!
-#endif
-
-
-/* Values for the Tx command-status descriptor entry. */
-enum td_cmdstat {
-       txOwn = 1 << 31,
-       txAutoMode = 1 << 30,
-       txEI = 1 << 23,
-       txGenCRC = 1 << 22,
-       txPad = 1 << 18,
-       txFirst = 1 << 17,
-       txLast = 1 << 16,
-       txErrorSummary = 1 << 15,
-       txReTxCntMask = 0x0f << 10,
-       txReTxCntBit = 10,
-       txCollision = 1 << 9,
-       txReTxLimit = 1 << 8,
-       txUnderrun = 1 << 6,
-       txLateCollision = 1 << 5
-};
-
-
-/* Values for the Rx command-status descriptor entry. */
-enum rd_cmdstat {
-       rxOwn = 1 << 31,
-       rxAutoMode = 1 << 30,
-       rxEI = 1 << 23,
-       rxFirst = 1 << 17,
-       rxLast = 1 << 16,
-       rxErrorSummary = 1 << 15,
-       rxIGMP = 1 << 14,
-       rxHashExpired = 1 << 13,
-       rxMissedFrame = 1 << 12,
-       rxFrameType = 1 << 11,
-       rxShortFrame = 1 << 8,
-       rxMaxFrameLen = 1 << 7,
-       rxOverrun = 1 << 6,
-       rxCollision = 1 << 4,
-       rxCRCError = 1
-};
-
-/* Bit fields of a Hash Table Entry */
-enum hash_table_entry {
-       hteValid = 1,
-       hteSkip = 2,
-       hteRD = 4
-};
-
-// The MIB counters
-typedef struct {
-       u32 byteReceived;
-       u32 byteSent;
-       u32 framesReceived;
-       u32 framesSent;
-       u32 totalByteReceived;
-       u32 totalFramesReceived;
-       u32 broadcastFramesReceived;
-       u32 multicastFramesReceived;
-       u32 cRCError;
-       u32 oversizeFrames;
-       u32 fragments;
-       u32 jabber;
-       u32 collision;
-       u32 lateCollision;
-       u32 frames64;
-       u32 frames65_127;
-       u32 frames128_255;
-       u32 frames256_511;
-       u32 frames512_1023;
-       u32 frames1024_MaxSize;
-       u32 macRxError;
-       u32 droppedFrames;
-       u32 outMulticastFrames;
-       u32 outBroadcastFrames;
-       u32 undersizeFrames;
-} mib_counters_t;
-
-
-struct gt64240_private {
-       gt64240_rd_t *rx_ring;
-       gt64240_td_t *tx_ring;
-       // The Rx and Tx rings must be 16-byte aligned
-       dma_addr_t rx_ring_dma;
-       dma_addr_t tx_ring_dma;
-       char *hash_table;
-       // The Hash Table must be 8-byte aligned
-       dma_addr_t hash_table_dma;
-       int hash_mode;
-
-       // The Rx buffers must be 8-byte aligned
-       char *rx_buff;
-       dma_addr_t rx_buff_dma;
-       // Tx buffers (tx_skbuff[i]->data) with less than 8 bytes
-       // of payload must be 8-byte aligned
-       struct sk_buff *tx_skbuff[TX_RING_SIZE];
-       int rx_next_out;        /* The next free ring entry to receive */
-       int tx_next_in;         /* The next free ring entry to send */
-       int tx_next_out;        /* The last ring entry the ISR processed */
-       int tx_count;           /* current # of pkts waiting to be sent in Tx ring */
-       int intr_work_done;     /* number of Rx and Tx pkts processed in the isr */
-       int tx_full;            /* Tx ring is full */
-
-       mib_counters_t mib;
-       struct net_device_stats stats;
-
-       int io_size;
-       int port_num;           // 0 or 1
-       u32 port_offset;
-
-       int phy_addr;           // PHY address
-       u32 last_psr;           // last value of the port status register
-
-       int options;            /* User-settable misc. driver options. */
-       int drv_flags;
-       spinlock_t lock;        /* Serialise access to device */
-       struct mii_if_info mii_if;
-
-       u32 msg_enable;
-};
-
-#endif /* _GT64240ETH_H */
index 2a0d538b387fca39f69414aca82d6060ea371a0c..383cef1f5999fbe93e994ddaad893ea7a113d6f1 100644 (file)
@@ -671,10 +671,8 @@ static void irda_usb_net_timeout(struct net_device *netdev)
                         * Jean II */
                        done = 1;
                        break;
-               case -ECONNABORTED:             /* -103 */
-               case -ECONNRESET:               /* -104 */
-               case -ETIMEDOUT:                /* -110 */
-               case -ENOENT:                   /* -2 (urb unlinked by us)  */
+               case -ECONNRESET:
+               case -ENOENT:                   /* urb unlinked by us */
                default:                        /* ??? - Play safe */
                        urb->status = 0;
                        netif_wake_queue(self->netdev);
@@ -712,10 +710,8 @@ static void irda_usb_net_timeout(struct net_device *netdev)
                         * Jean II */
                        done = 1;
                        break;
-               case -ECONNABORTED:             /* -103 */
-               case -ECONNRESET:               /* -104 */
-               case -ETIMEDOUT:                /* -110 */
-               case -ENOENT:                   /* -2 (urb unlinked by us)  */
+               case -ECONNRESET:
+               case -ENOENT:                   /* urb unlinked by us */
                default:                        /* ??? - Play safe */
                        if(skb != NULL) {
                                dev_kfree_skb_any(skb);
@@ -845,14 +841,14 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
                        self->stats.rx_crc_errors++;    
                        /* Also precursor to a hot-unplug on UHCI. */
                        /* Fallthrough... */
-               case -ECONNRESET:               /* -104 */
+               case -ECONNRESET:
                        /* Random error, if I remember correctly */
                        /* uhci_cleanup_unlink() is going to kill the Rx
                         * URB just after we return. No problem, at this
                         * point the URB will be idle ;-) - Jean II */
-               case -ESHUTDOWN:                /* -108 */
+               case -ESHUTDOWN:
                        /* That's usually a hot-unplug. Submit will fail... */
-               case -ETIMEDOUT:                /* -110 */
+               case -ETIME:
                        /* Usually precursor to a hot-unplug on OHCI. */
                default:
                        self->stats.rx_errors++;
index a82a4ba8de4fc2a6f27280a127a5997dfbd39637..c37f0bc4c7f9f7257d8f3edad087a30b5c1e347a 100644 (file)
@@ -58,7 +58,7 @@ typedef void irqreturn_t;
 
 /* PDE() introduced in 2.5.4 */
 #ifdef CONFIG_PROC_FS
-#define PDE(inode) ((inode)->u.generic_ip)
+#define PDE(inode) ((inode)->i_private)
 #endif
 
 /* irda crc16 calculation exported in 2.5.42 */
index 0fa8e4d2276993984075a7e763f921470534e8b9..d663289754255015d90fc7e4cd3b3342e31084bc 100644 (file)
@@ -343,6 +343,7 @@ static struct eisa_device_id ne3210_ids[] = {
        { "NVL1801" },
        { "" },
 };
+MODULE_DEVICE_TABLE(eisa, ne3210_ids);
 
 static struct eisa_driver ne3210_eisa_driver = {
        .id_table = ne3210_ids,
index 2d1ecfdc80dbecbc5e345d4524803ecf49bba114..ecd3da151e2d2a17eca4dabf378a3cef41a341df 100644 (file)
@@ -522,7 +522,7 @@ EXPORT_SYMBOL(genphy_read_status);
 
 static int genphy_config_init(struct phy_device *phydev)
 {
-       u32 val;
+       int val;
        u32 features;
 
        /* For now, I'll claim that the generic driver supports
index f5dbeb27b6f082553974d8b057f2916266ed92e9..1bf23e41f5804f8f697b347f895b72920cd719aa 100644 (file)
@@ -2904,7 +2904,7 @@ static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device
 {
        u64 val64 = 0x0;
        nic_t *sp = dev->priv;
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
        //address transaction
        val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
@@ -2953,7 +2953,7 @@ static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
        u64 val64 = 0x0;
        u64 rval64 = 0x0;
        nic_t *sp = dev->priv;
-       XENA_dev_config_t *bar0 = (XENA_dev_config_t *)sp->bar0;
+       XENA_dev_config_t __iomem *bar0 = sp->bar0;
 
        /* address transaction */
        val64 = val64 | MDIO_MMD_INDX_ADDR(addr)
@@ -3276,7 +3276,7 @@ static void alarm_intr_handler(struct s2io_nic *nic)
  *   SUCCESS on success and FAILURE on failure.
  */
 
-static int wait_for_cmd_complete(void *addr, u64 busy_bit)
+static int wait_for_cmd_complete(void __iomem *addr, u64 busy_bit)
 {
        int ret = FAILURE, cnt = 0;
        u64 val64;
@@ -4303,11 +4303,11 @@ static struct net_device_stats *s2io_get_stats(struct net_device *dev)
        sp->stats.tx_errors =
                le32_to_cpu(mac_control->stats_info->tmac_any_err_frms);
        sp->stats.rx_errors =
-               le32_to_cpu(mac_control->stats_info->rmac_drop_frms);
+               le64_to_cpu(mac_control->stats_info->rmac_drop_frms);
        sp->stats.multicast =
                le32_to_cpu(mac_control->stats_info->rmac_vld_mcst_frms);
        sp->stats.rx_length_errors =
-               le32_to_cpu(mac_control->stats_info->rmac_long_frms);
+               le64_to_cpu(mac_control->stats_info->rmac_long_frms);
 
        return (&sp->stats);
 }
index 9142d91355bc9a51b2e0283b2328d0e84dab0c44..705e9a8fa30fb454b60759331910193136316bf1 100644 (file)
@@ -58,6 +58,7 @@
 #define TX_WATCHDOG            (5 * HZ)
 #define NAPI_WEIGHT            64
 #define BLINK_MS               250
+#define LINK_HZ                        (HZ/2)
 
 MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
 MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
@@ -605,7 +606,12 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
        if (hw->chip_id == CHIP_ID_GENESIS) {
                switch (mode) {
                case LED_MODE_OFF:
-                       xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+                       if (hw->phy_type == SK_PHY_BCOM)
+                               xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF);
+                       else {
+                               skge_write32(hw, SK_REG(port, TX_LED_VAL), 0);
+                               skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_T_OFF);
+                       }
                        skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF);
                        skge_write32(hw, SK_REG(port, RX_LED_VAL), 0);
                        skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF);
@@ -625,8 +631,14 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
                        skge_write32(hw, SK_REG(port, RX_LED_VAL), 100);
                        skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START);
 
-                       xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
-                       break;
+                       if (hw->phy_type == SK_PHY_BCOM)
+                               xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON);
+                       else {
+                               skge_write8(hw, SK_REG(port, TX_LED_TST), LED_T_ON);
+                               skge_write32(hw, SK_REG(port, TX_LED_VAL), 100);
+                               skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START);
+                       }
+
                }
        } else {
                switch (mode) {
@@ -879,6 +891,9 @@ static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val)
        xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
        *val = xm_read16(hw, port, XM_PHY_DATA);
 
+       if (hw->phy_type == SK_PHY_XMAC)
+               goto ready;
+
        for (i = 0; i < PHY_RETRIES; i++) {
                if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY)
                        goto ready;
@@ -965,7 +980,8 @@ static void genesis_reset(struct skge_hw *hw, int port)
        xm_write16(hw, port, XM_RX_CMD, 0);     /* reset RX CMD Reg */
 
        /* disable Broadcom PHY IRQ */
-       xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
+       if (hw->phy_type == SK_PHY_BCOM)
+               xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
 
        xm_outhash(hw, port, XM_HSM, zero);
 }
@@ -1000,60 +1016,64 @@ static void bcom_check_link(struct skge_hw *hw, int port)
 
                if (netif_carrier_ok(dev))
                        skge_link_down(skge);
-       } else {
-               if (skge->autoneg == AUTONEG_ENABLE &&
-                   (status & PHY_ST_AN_OVER)) {
-                       u16 lpa = xm_phy_read(hw, port, PHY_BCOM_AUNE_LP);
-                       u16 aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
-
-                       if (lpa & PHY_B_AN_RF) {
-                               printk(KERN_NOTICE PFX "%s: remote fault\n",
-                                      dev->name);
-                               return;
-                       }
+               return;
+       }
 
-                       /* Check Duplex mismatch */
-                       switch (aux & PHY_B_AS_AN_RES_MSK) {
-                       case PHY_B_RES_1000FD:
-                               skge->duplex = DUPLEX_FULL;
-                               break;
-                       case PHY_B_RES_1000HD:
-                               skge->duplex = DUPLEX_HALF;
-                               break;
-                       default:
-                               printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
-                                      dev->name);
-                               return;
-                       }
+       if (skge->autoneg == AUTONEG_ENABLE) {
+               u16 lpa, aux;
 
+               if (!(status & PHY_ST_AN_OVER))
+                       return;
 
-                       /* We are using IEEE 802.3z/D5.0 Table 37-4 */
-                       switch (aux & PHY_B_AS_PAUSE_MSK) {
-                       case PHY_B_AS_PAUSE_MSK:
-                               skge->flow_control = FLOW_MODE_SYMMETRIC;
-                               break;
-                       case PHY_B_AS_PRR:
-                               skge->flow_control = FLOW_MODE_REM_SEND;
-                               break;
-                       case PHY_B_AS_PRT:
-                               skge->flow_control = FLOW_MODE_LOC_SEND;
-                               break;
-                       default:
-                               skge->flow_control = FLOW_MODE_NONE;
-                       }
+               lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
+               if (lpa & PHY_B_AN_RF) {
+                       printk(KERN_NOTICE PFX "%s: remote fault\n",
+                              dev->name);
+                       return;
+               }
 
-                       skge->speed = SPEED_1000;
+               aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
+
+               /* Check Duplex mismatch */
+               switch (aux & PHY_B_AS_AN_RES_MSK) {
+               case PHY_B_RES_1000FD:
+                       skge->duplex = DUPLEX_FULL;
+                       break;
+               case PHY_B_RES_1000HD:
+                       skge->duplex = DUPLEX_HALF;
+                       break;
+               default:
+                       printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
+                              dev->name);
+                       return;
                }
 
-               if (!netif_carrier_ok(dev))
-                       genesis_link_up(skge);
+
+               /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+               switch (aux & PHY_B_AS_PAUSE_MSK) {
+               case PHY_B_AS_PAUSE_MSK:
+                       skge->flow_control = FLOW_MODE_SYMMETRIC;
+                       break;
+               case PHY_B_AS_PRR:
+                       skge->flow_control = FLOW_MODE_REM_SEND;
+                       break;
+               case PHY_B_AS_PRT:
+                       skge->flow_control = FLOW_MODE_LOC_SEND;
+                       break;
+               default:
+                       skge->flow_control = FLOW_MODE_NONE;
+               }
+               skge->speed = SPEED_1000;
        }
+
+       if (!netif_carrier_ok(dev))
+               genesis_link_up(skge);
 }
 
 /* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional
  * Phy on for 100 or 10Mbit operation
  */
-static void bcom_phy_init(struct skge_port *skge, int jumbo)
+static void bcom_phy_init(struct skge_port *skge)
 {
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
@@ -1144,7 +1164,7 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
                     phy_pause_map[skge->flow_control] | PHY_AN_CSMA);
 
        /* Handle Jumbo frames */
-       if (jumbo) {
+       if (hw->dev[port]->mtu > ETH_DATA_LEN) {
                xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
                             PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK);
 
@@ -1157,8 +1177,154 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
 
        /* Use link status change interrupt */
        xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+}
 
-       bcom_check_link(hw, port);
+static void xm_phy_init(struct skge_port *skge)
+{
+       struct skge_hw *hw = skge->hw;
+       int port = skge->port;
+       u16 ctrl = 0;
+
+       if (skge->autoneg == AUTONEG_ENABLE) {
+               if (skge->advertising & ADVERTISED_1000baseT_Half)
+                       ctrl |= PHY_X_AN_HD;
+               if (skge->advertising & ADVERTISED_1000baseT_Full)
+                       ctrl |= PHY_X_AN_FD;
+
+               switch(skge->flow_control) {
+               case FLOW_MODE_NONE:
+                       ctrl |= PHY_X_P_NO_PAUSE;
+                       break;
+               case FLOW_MODE_LOC_SEND:
+                       ctrl |= PHY_X_P_ASYM_MD;
+                       break;
+               case FLOW_MODE_SYMMETRIC:
+                       ctrl |= PHY_X_P_BOTH_MD;
+                       break;
+               }
+
+               xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl);
+
+               /* Restart Auto-negotiation */
+               ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
+       } else {
+               /* Set DuplexMode in Config register */
+               if (skge->duplex == DUPLEX_FULL)
+                       ctrl |= PHY_CT_DUP_MD;
+               /*
+                * Do NOT enable Auto-negotiation here. This would hold
+                * the link down because no IDLEs are transmitted
+                */
+       }
+
+       xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl);
+
+       /* Poll PHY for status changes */
+       schedule_delayed_work(&skge->link_thread, LINK_HZ);
+}
+
+static void xm_check_link(struct net_device *dev)
+{
+       struct skge_port *skge = netdev_priv(dev);
+       struct skge_hw *hw = skge->hw;
+       int port = skge->port;
+       u16 status;
+
+       /* read twice because of latch */
+       (void) xm_phy_read(hw, port, PHY_XMAC_STAT);
+       status = xm_phy_read(hw, port, PHY_XMAC_STAT);
+
+       if ((status & PHY_ST_LSYNC) == 0) {
+               u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
+               cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+               xm_write16(hw, port, XM_MMU_CMD, cmd);
+               /* dummy read to ensure writing */
+               (void) xm_read16(hw, port, XM_MMU_CMD);
+
+               if (netif_carrier_ok(dev))
+                       skge_link_down(skge);
+               return;
+       }
+
+       if (skge->autoneg == AUTONEG_ENABLE) {
+               u16 lpa, res;
+
+               if (!(status & PHY_ST_AN_OVER))
+                       return;
+
+               lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP);
+               if (lpa & PHY_B_AN_RF) {
+                       printk(KERN_NOTICE PFX "%s: remote fault\n",
+                              dev->name);
+                       return;
+               }
+
+               res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI);
+
+               /* Check Duplex mismatch */
+               switch (res & (PHY_X_RS_HD | PHY_X_RS_FD)) {
+               case PHY_X_RS_FD:
+                       skge->duplex = DUPLEX_FULL;
+                       break;
+               case PHY_X_RS_HD:
+                       skge->duplex = DUPLEX_HALF;
+                       break;
+               default:
+                       printk(KERN_NOTICE PFX "%s: duplex mismatch\n",
+                              dev->name);
+                       return;
+               }
+
+               /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+               if (lpa & PHY_X_P_SYM_MD)
+                       skge->flow_control = FLOW_MODE_SYMMETRIC;
+               else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD)
+                       skge->flow_control = FLOW_MODE_REM_SEND;
+               else if ((lpa & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD)
+                       skge->flow_control = FLOW_MODE_LOC_SEND;
+               else
+                       skge->flow_control = FLOW_MODE_NONE;
+
+
+               skge->speed = SPEED_1000;
+       }
+
+       if (!netif_carrier_ok(dev))
+               genesis_link_up(skge);
+}
+
+/* Poll to check for link coming up.
+ * Since internal PHY is wired to a level triggered pin, can't
+ * get an interrupt when carrier is detected.
+ */
+static void xm_link_timer(void *arg)
+{
+       struct net_device *dev = arg;
+       struct skge_port *skge = netdev_priv(arg);
+       struct skge_hw *hw = skge->hw;
+       int port = skge->port;
+
+       if (!netif_running(dev))
+               return;
+
+       if (netif_carrier_ok(dev)) {
+               xm_read16(hw, port, XM_ISRC);
+               if (!(xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS))
+                       goto nochange;
+       } else {
+               if (xm_read32(hw, port, XM_GP_PORT) & XM_GP_INP_ASS)
+                       goto nochange;
+               xm_read16(hw, port, XM_ISRC);
+               if (xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)
+                       goto nochange;
+       }
+
+       mutex_lock(&hw->phy_mutex);
+       xm_check_link(dev);
+       mutex_unlock(&hw->phy_mutex);
+
+nochange:
+       schedule_delayed_work(&skge->link_thread, LINK_HZ);
 }
 
 static void genesis_mac_init(struct skge_hw *hw, int port)
@@ -1189,20 +1355,29 @@ static void genesis_mac_init(struct skge_hw *hw, int port)
         * namely for the 1000baseTX cards that use the XMAC's
         * GMII mode.
         */
-       /* Take external Phy out of reset */
-       r = skge_read32(hw, B2_GP_IO);
-       if (port == 0)
-               r |= GP_DIR_0|GP_IO_0;
-       else
-               r |= GP_DIR_2|GP_IO_2;
+       if (hw->phy_type != SK_PHY_XMAC) {
+               /* Take external Phy out of reset */
+               r = skge_read32(hw, B2_GP_IO);
+               if (port == 0)
+                       r |= GP_DIR_0|GP_IO_0;
+               else
+                       r |= GP_DIR_2|GP_IO_2;
 
-       skge_write32(hw, B2_GP_IO, r);
+               skge_write32(hw, B2_GP_IO, r);
 
+               /* Enable GMII interface */
+               xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
+       }
 
-       /* Enable GMII interface */
-       xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
 
-       bcom_phy_init(skge, jumbo);
+       switch(hw->phy_type) {
+       case SK_PHY_XMAC:
+               xm_phy_init(skge);
+               break;
+       case SK_PHY_BCOM:
+               bcom_phy_init(skge);
+               bcom_check_link(hw, port);
+       }
 
        /* Set Station Address */
        xm_outaddr(hw, port, XM_SA, dev->dev_addr);
@@ -1335,16 +1510,18 @@ static void genesis_stop(struct skge_port *skge)
        skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
 
        /* For external PHYs there must be special handling */
-       reg = skge_read32(hw, B2_GP_IO);
-       if (port == 0) {
-               reg |= GP_DIR_0;
-               reg &= ~GP_IO_0;
-       } else {
-               reg |= GP_DIR_2;
-               reg &= ~GP_IO_2;
+       if (hw->phy_type != SK_PHY_XMAC) {
+               reg = skge_read32(hw, B2_GP_IO);
+               if (port == 0) {
+                       reg |= GP_DIR_0;
+                       reg &= ~GP_IO_0;
+               } else {
+                       reg |= GP_DIR_2;
+                       reg &= ~GP_IO_2;
+               }
+               skge_write32(hw, B2_GP_IO, reg);
+               skge_read32(hw, B2_GP_IO);
        }
-       skge_write32(hw, B2_GP_IO, reg);
-       skge_read32(hw, B2_GP_IO);
 
        xm_write16(hw, port, XM_MMU_CMD,
                        xm_read16(hw, port, XM_MMU_CMD)
@@ -1406,7 +1583,7 @@ static void genesis_link_up(struct skge_port *skge)
        struct skge_hw *hw = skge->hw;
        int port = skge->port;
        u16 cmd;
-       u32 mode, msk;
+       u32 mode;
 
        cmd = xm_read16(hw, port, XM_MMU_CMD);
 
@@ -1454,27 +1631,24 @@ static void genesis_link_up(struct skge_port *skge)
        }
 
        xm_write32(hw, port, XM_MODE, mode);
-
-       msk = XM_DEF_MSK;
-       /* disable GP0 interrupt bit for external Phy */
-       msk |= XM_IS_INP_ASS;
-
-       xm_write16(hw, port, XM_IMSK, msk);
+       xm_write16(hw, port, XM_IMSK, XM_DEF_MSK);
        xm_read16(hw, port, XM_ISRC);
 
        /* get MMU Command Reg. */
        cmd = xm_read16(hw, port, XM_MMU_CMD);
-       if (skge->duplex == DUPLEX_FULL)
+       if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL)
                cmd |= XM_MMU_GMII_FD;
 
        /*
         * Workaround BCOM Errata (#10523) for all BCom Phys
         * Enable Power Management after link up
         */
-       xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
-                    xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
-                    & ~PHY_B_AC_DIS_PM);
-       xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+       if (hw->phy_type == SK_PHY_BCOM) {
+               xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
+                            xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
+                            & ~PHY_B_AC_DIS_PM);
+               xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+       }
 
        /* enable Rx/Tx */
        xm_write16(hw, port, XM_MMU_CMD,
@@ -2240,6 +2414,8 @@ static int skge_down(struct net_device *dev)
                printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
 
        netif_stop_queue(dev);
+       if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC)
+               cancel_rearming_delayed_work(&skge->link_thread);
 
        skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
        if (hw->chip_id == CHIP_ID_GENESIS)
@@ -2862,7 +3038,7 @@ static void skge_extirq(void *arg)
                if (netif_running(dev)) {
                        if (hw->chip_id != CHIP_ID_GENESIS)
                                yukon_phy_intr(skge);
-                       else
+                       else if (hw->phy_type == SK_PHY_BCOM)
                                bcom_phy_intr(skge);
                }
        }
@@ -3014,7 +3190,7 @@ static int skge_reset(struct skge_hw *hw)
 {
        u32 reg;
        u16 ctst, pci_status;
-       u8 t8, mac_cfg, pmd_type, phy_type;
+       u8 t8, mac_cfg, pmd_type;
        int i;
 
        ctst = skge_read16(hw, B0_CTST);
@@ -3038,19 +3214,22 @@ static int skge_reset(struct skge_hw *hw)
                     ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
 
        hw->chip_id = skge_read8(hw, B2_CHIP_ID);
-       phy_type = skge_read8(hw, B2_E_1) & 0xf;
+       hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
        pmd_type = skge_read8(hw, B2_PMD_TYP);
        hw->copper = (pmd_type == 'T' || pmd_type == '1');
 
        switch (hw->chip_id) {
        case CHIP_ID_GENESIS:
-               switch (phy_type) {
+               switch (hw->phy_type) {
+               case SK_PHY_XMAC:
+                       hw->phy_addr = PHY_ADDR_XMAC;
+                       break;
                case SK_PHY_BCOM:
                        hw->phy_addr = PHY_ADDR_BCOM;
                        break;
                default:
                        printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n",
-                              pci_name(hw->pdev), phy_type);
+                              pci_name(hw->pdev), hw->phy_type);
                        return -EOPNOTSUPP;
                }
                break;
@@ -3058,7 +3237,7 @@ static int skge_reset(struct skge_hw *hw)
        case CHIP_ID_YUKON:
        case CHIP_ID_YUKON_LITE:
        case CHIP_ID_YUKON_LP:
-               if (phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
+               if (hw->phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S')
                        hw->copper = 1;
 
                hw->phy_addr = PHY_ADDR_MARV;
@@ -3089,10 +3268,13 @@ static int skge_reset(struct skge_hw *hw)
        else
                hw->ram_size = t8 * 4096;
 
-       hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1;
+       hw->intr_mask = IS_HW_ERR | IS_PORT_1;
        if (hw->ports > 1)
                hw->intr_mask |= IS_PORT_2;
 
+       if (!(hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC))
+               hw->intr_mask |= IS_EXT_REG;
+
        if (hw->chip_id == CHIP_ID_GENESIS)
                genesis_init(hw);
        else {
@@ -3226,6 +3408,9 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
 
        skge->port = port;
 
+       /* Only used for Genesis XMAC */
+       INIT_WORK(&skge->link_thread, xm_link_timer, dev);
+
        if (hw->chip_id != CHIP_ID_GENESIS) {
                dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
                skge->rx_csum = 1;
index 79e09271bcf9b5e8f8d25553595b5d020e9e050c..d0b47d46cf9d23701239d7b5c6d5c7d32c477c3d 100644 (file)
@@ -934,7 +934,7 @@ enum {
        PHY_XMAC_AUNE_ADV       = 0x04,/* 16 bit r/w    Auto-Neg. Advertisement */
        PHY_XMAC_AUNE_LP        = 0x05,/* 16 bit r/o    Link Partner Abi Reg */
        PHY_XMAC_AUNE_EXP       = 0x06,/* 16 bit r/o    Auto-Neg. Expansion Reg */
-       PHY_XMAC_NEPG   = 0x07,/* 16 bit r/w    Next Page Register */
+       PHY_XMAC_NEPG           = 0x07,/* 16 bit r/w    Next Page Register */
        PHY_XMAC_NEPG_LP        = 0x08,/* 16 bit r/o    Next Page Link Partner */
 
        PHY_XMAC_EXT_STAT       = 0x0f,/* 16 bit r/o    Ext Status Register */
@@ -1097,13 +1097,36 @@ enum {
 
 /* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */
 enum {
-       PHY_X_P_NO_PAUSE        = 0<<7,/* Bit  8..7:    no Pause Mode */
+       PHY_X_P_NO_PAUSE= 0<<7,/* Bit  8..7:    no Pause Mode */
        PHY_X_P_SYM_MD  = 1<<7, /* Bit  8..7:   symmetric Pause Mode */
        PHY_X_P_ASYM_MD = 2<<7,/* Bit  8..7:    asymmetric Pause Mode */
        PHY_X_P_BOTH_MD = 3<<7,/* Bit  8..7:    both Pause Mode */
 };
 
 
+/*****  PHY_XMAC_EXT_STAT      16 bit r/w      Extended Status Register *****/
+enum {
+       PHY_X_EX_FD     = 1<<15, /* Bit 15:     Device Supports Full Duplex */
+       PHY_X_EX_HD     = 1<<14, /* Bit 14:     Device Supports Half Duplex */
+};
+
+/*****  PHY_XMAC_RES_ABI       16 bit r/o      PHY Resolved Ability *****/
+enum {
+       PHY_X_RS_PAUSE  = 3<<7, /* Bit  8..7:   selected Pause Mode */
+       PHY_X_RS_HD     = 1<<6, /* Bit  6:      Half Duplex Mode selected */
+       PHY_X_RS_FD     = 1<<5, /* Bit  5:      Full Duplex Mode selected */
+       PHY_X_RS_ABLMIS = 1<<4, /* Bit  4:      duplex or pause cap mismatch */
+       PHY_X_RS_PAUMIS = 1<<3, /* Bit  3:      pause capability mismatch */
+};
+
+/* Remote Fault Bits (PHY_X_AN_RFB) encoding */
+enum {
+       X_RFB_OK        = 0<<12,/* Bit 13..12   No errors, Link OK */
+       X_RFB_LF        = 1<<12,/* Bit 13..12   Link Failure */
+       X_RFB_OFF       = 2<<12,/* Bit 13..12   Offline */
+       X_RFB_AN_ERR    = 3<<12,/* Bit 13..12   Auto-Negotiation Error */
+};
+
 /* Broadcom-Specific */
 /*****  PHY_BCOM_1000T_CTRL    16 bit r/w      1000Base-T Control Reg *****/
 enum {
@@ -2158,8 +2181,8 @@ enum {
        XM_IS_LNK_AE    = 1<<14, /* Bit 14:     Link Asynchronous Event */
        XM_IS_TX_ABORT  = 1<<13, /* Bit 13:     Transmit Abort, late Col. etc */
        XM_IS_FRC_INT   = 1<<12, /* Bit 12:     Force INT bit set in GP */
-       XM_IS_INP_ASS   = 1<<11,        /* Bit 11:      Input Asserted, GP bit 0 set */
-       XM_IS_LIPA_RC   = 1<<10,        /* Bit 10:      Link Partner requests config */
+       XM_IS_INP_ASS   = 1<<11, /* Bit 11:     Input Asserted, GP bit 0 set */
+       XM_IS_LIPA_RC   = 1<<10, /* Bit 10:     Link Partner requests config */
        XM_IS_RX_PAGE   = 1<<9, /* Bit  9:      Page Received */
        XM_IS_TX_PAGE   = 1<<8, /* Bit  8:      Next Page Loaded for Transmit */
        XM_IS_AND       = 1<<7, /* Bit  7:      Auto-Negotiation Done */
@@ -2172,9 +2195,7 @@ enum {
        XM_IS_RX_COMP   = 1<<0, /* Bit  0:      Frame Rx Complete */
 };
 
-#define XM_DEF_MSK     (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | \
-                          XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | \
-                          XM_IS_RXF_OV | XM_IS_TXF_UR))
+#define XM_DEF_MSK     (~(XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_RXF_OV | XM_IS_TXF_UR))
 
 
 /*     XM_HW_CFG       16 bit r/w      Hardware Config Register */
@@ -2396,6 +2417,7 @@ struct skge_hw {
        u8                   chip_rev;
        u8                   copper;
        u8                   ports;
+       u8                   phy_type;
 
        u32                  ram_size;
        u32                  ram_offset;
@@ -2422,6 +2444,7 @@ struct skge_port {
 
        struct net_device_stats net_stats;
 
+       struct work_struct   link_thread;
        u8                   rx_csum;
        u8                   blink_on;
        u8                   flow_control;
index 7aa7fbac8224a385f91c8fd696daeab35d1aba58..c660e33f43a2e35bbc7723ced259629bd740936f 100644 (file)
@@ -379,6 +379,24 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r,
 
 #define SMC_IRQ_FLAGS          (0)
 
+#elif  defined(CONFIG_ARCH_VERSATILE)
+
+#define SMC_CAN_USE_8BIT       1
+#define SMC_CAN_USE_16BIT      1
+#define SMC_CAN_USE_32BIT      1
+#define SMC_NOWAIT             1
+
+#define SMC_inb(a, r)          readb((a) + (r))
+#define SMC_inw(a, r)          readw((a) + (r))
+#define SMC_inl(a, r)          readl((a) + (r))
+#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
+#define SMC_outw(v, a, r)      writew(v, (a) + (r))
+#define SMC_outl(v, a, r)      writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
+
+#define SMC_IRQ_FLAGS          (0)
+
 #else
 
 #define SMC_CAN_USE_8BIT       1
index 3fd7a4fee6658e3504fe4da58a8fa167f19c2672..e6f90427160cf162d82682a409af375eb6e4903b 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/se/se.h>
+#include <asm/se.h>
 #include <asm/machvec.h>
 #ifdef CONFIG_SH_STANDARD_BIOS
 #include <asm/sh_bios.h>
index 0d66700c6cedb3d9934a815f15c7ac2e2e327931..bfc8c3eae9a1de7123c2dba1f05932e405215c16 100644 (file)
@@ -1876,7 +1876,6 @@ static int sprintf_info(char *buffer, struct net_device *dev)
                datap[size+1]=io_word & 0xff;
        }
 
-
        size = sprintf(buffer, "\n%6s: Adapter Address   : Node Address      : Functional Addr\n", dev->name);
 
        size += sprintf(buffer + size,
@@ -1932,64 +1931,6 @@ static int sprintf_info(char *buffer, struct net_device *dev)
 #endif
 #endif
 
-#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static int streamer_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-        int i;
-       struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv;
-       u8 __iomem *streamer_mmio = streamer_priv->streamer_mmio;
-
-       switch(cmd) {
-       case IOCTL_SISR_MASK:
-               writew(SISR_MI, streamer_mmio + SISR_MASK_SUM);
-               break;
-       case IOCTL_SPIN_LOCK_TEST:
-               printk(KERN_INFO "spin_lock() called.\n");
-               spin_lock(&streamer_priv->streamer_lock);
-               spin_unlock(&streamer_priv->streamer_lock);
-               printk(KERN_INFO "spin_unlock() finished.\n");
-               break;
-       case IOCTL_PRINT_BDAS:
-               printk(KERN_INFO "bdas: RXBDA: %x RXLBDA: %x TX2FDA: %x TX2LFDA: %x\n",
-                      readw(streamer_mmio + RXBDA),
-                      readw(streamer_mmio + RXLBDA),
-                      readw(streamer_mmio + TX2FDA),
-                      readw(streamer_mmio + TX2LFDA));
-               break;
-       case IOCTL_PRINT_REGISTERS:
-               printk(KERN_INFO "registers:\n");
-               printk(KERN_INFO "SISR: %04x MISR: %04x LISR: %04x BCTL: %04x BMCTL: %04x\nmask  %04x mask  %04x\n", 
-                      readw(streamer_mmio + SISR),
-                      readw(streamer_mmio + MISR_RUM),
-                      readw(streamer_mmio + LISR),
-                      readw(streamer_mmio + BCTL),
-                      readw(streamer_mmio + BMCTL_SUM),
-                      readw(streamer_mmio + SISR_MASK),
-                      readw(streamer_mmio + MISR_MASK));
-               break;
-       case IOCTL_PRINT_RX_BUFS:
-               printk(KERN_INFO "Print rx bufs:\n");
-               for(i=0; i<STREAMER_RX_RING_SIZE; i++)
-                       printk(KERN_INFO "rx_ring %d status: 0x%x\n", i, 
-                              streamer_priv->streamer_rx_ring[i].status);
-               break;
-       case IOCTL_PRINT_TX_BUFS:
-               printk(KERN_INFO "Print tx bufs:\n");
-               for(i=0; i<STREAMER_TX_RING_SIZE; i++)
-                       printk(KERN_INFO "tx_ring %d status: 0x%x\n", i, 
-                              streamer_priv->streamer_tx_ring[i].status);
-               break;
-       case IOCTL_RX_CMD:
-               streamer_rx(dev);
-               printk(KERN_INFO "Sent rx command.\n");
-               break;
-       default:
-               printk(KERN_INFO "Bad ioctl!\n");
-       }
-       return 0;
-}
-#endif
-
 static struct pci_driver streamer_pci_driver = {
   .name     = "lanstreamer",
   .id_table = streamer_pci_tbl,
index 5557d8e1e22de6cec1b3ea0c46c65915c490bdc2..e7bb3494afc74609e53413a97c517d4bd9d37f7d 100644 (file)
 
 #include <linux/version.h>
 
-#if STREAMER_IOCTL && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-#include <asm/ioctl.h>
-#define IOCTL_PRINT_RX_BUFS   SIOCDEVPRIVATE
-#define IOCTL_PRINT_TX_BUFS   SIOCDEVPRIVATE+1
-#define IOCTL_RX_CMD          SIOCDEVPRIVATE+2
-#define IOCTL_TX_CMD          SIOCDEVPRIVATE+3
-#define IOCTL_PRINT_REGISTERS SIOCDEVPRIVATE+4
-#define IOCTL_PRINT_BDAS      SIOCDEVPRIVATE+5
-#define IOCTL_SPIN_LOCK_TEST  SIOCDEVPRIVATE+6
-#define IOCTL_SISR_MASK       SIOCDEVPRIVATE+7
-#endif
-
 /* MAX_INTR - the maximum number of times we can loop
  * inside the interrupt function before returning
  * control to the OS (maximum value is 256)
index e661d0a9cc64d5be35fc42ab81c402dd9970cea6..fb5fa7d688886afa5b4f9c2fd0f330533db29934 100644 (file)
@@ -2114,6 +2114,7 @@ static struct eisa_device_id de4x5_eisa_ids[] = {
         { "DEC4250", 0 },      /* 0 is the board name index... */
         { "" }
 };
+MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
 
 static struct eisa_driver de4x5_eisa_driver = {
         .id_table = de4x5_eisa_ids,
index 8f6f6fd8b87d3c26323b1b5a670a553afbe80586..d5c32e9caa978fe1c6e8f1e4a6359bd66245b1a8 100644 (file)
@@ -333,11 +333,7 @@ enum state_values {
 #define TYPHOON_RESET_TIMEOUT_NOSLEEP  ((6 * 1000000) / TYPHOON_UDELAY)
 #define TYPHOON_WAIT_TIMEOUT           ((1000000 / 2) / TYPHOON_UDELAY)
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 28)
-#define typhoon_synchronize_irq(x) synchronize_irq()
-#else
 #define typhoon_synchronize_irq(x) synchronize_irq(x)
-#endif
 
 #if defined(NETIF_F_TSO)
 #define skb_tso_size(x)                (skb_shinfo(x)->gso_size)
index 54b8e492ef97dca1b16c99441f674a76767ea963..58b7efbb075015462469454e0a174805038edeb7 100644 (file)
@@ -154,7 +154,7 @@ config HDLC
          If unsure, say N.
 
 config HDLC_RAW
-       bool "Raw HDLC support"
+       tristate "Raw HDLC support"
        depends on HDLC
        help
          Generic HDLC driver supporting raw HDLC over WAN connections.
@@ -162,7 +162,7 @@ config HDLC_RAW
          If unsure, say N.
 
 config HDLC_RAW_ETH
-       bool "Raw HDLC Ethernet device support"
+       tristate "Raw HDLC Ethernet device support"
        depends on HDLC
        help
          Generic HDLC driver supporting raw HDLC Ethernet device emulation
@@ -173,7 +173,7 @@ config HDLC_RAW_ETH
          If unsure, say N.
 
 config HDLC_CISCO
-       bool "Cisco HDLC support"
+       tristate "Cisco HDLC support"
        depends on HDLC
        help
          Generic HDLC driver supporting Cisco HDLC over WAN connections.
@@ -181,7 +181,7 @@ config HDLC_CISCO
          If unsure, say N.
 
 config HDLC_FR
-       bool "Frame Relay support"
+       tristate "Frame Relay support"
        depends on HDLC
        help
          Generic HDLC driver supporting Frame Relay over WAN connections.
@@ -189,7 +189,7 @@ config HDLC_FR
          If unsure, say N.
 
 config HDLC_PPP
-       bool "Synchronous Point-to-Point Protocol (PPP) support"
+       tristate "Synchronous Point-to-Point Protocol (PPP) support"
        depends on HDLC
        help
          Generic HDLC driver supporting PPP over WAN connections.
@@ -197,7 +197,7 @@ config HDLC_PPP
          If unsure, say N.
 
 config HDLC_X25
-       bool "X.25 protocol support"
+       tristate "X.25 protocol support"
        depends on HDLC && (LAPB=m && HDLC=m || LAPB=y)
        help
          Generic HDLC driver supporting X.25 over WAN connections.
index 316ca6869d5e83542085eb937b891f9554141d27..83ec2c87ba3f34fea00937247f9e4e64bce65c67 100644 (file)
@@ -9,14 +9,13 @@ cyclomx-y                       := cycx_main.o
 cyclomx-$(CONFIG_CYCLOMX_X25)  += cycx_x25.o
 cyclomx-objs                   := $(cyclomx-y)  
 
-hdlc-y                         := hdlc_generic.o
-hdlc-$(CONFIG_HDLC_RAW)                += hdlc_raw.o
-hdlc-$(CONFIG_HDLC_RAW_ETH)    += hdlc_raw_eth.o
-hdlc-$(CONFIG_HDLC_CISCO)      += hdlc_cisco.o
-hdlc-$(CONFIG_HDLC_FR)         += hdlc_fr.o
-hdlc-$(CONFIG_HDLC_PPP)                += hdlc_ppp.o
-hdlc-$(CONFIG_HDLC_X25)                += hdlc_x25.o
-hdlc-objs                      := $(hdlc-y)
+obj-$(CONFIG_HDLC)             += hdlc.o
+obj-$(CONFIG_HDLC_RAW)         += hdlc_raw.o
+obj-$(CONFIG_HDLC_RAW_ETH)     += hdlc_raw_eth.o
+obj-$(CONFIG_HDLC_CISCO)       += hdlc_cisco.o
+obj-$(CONFIG_HDLC_FR)          += hdlc_fr.o
+obj-$(CONFIG_HDLC_PPP)         += hdlc_ppp.o   syncppp.o
+obj-$(CONFIG_HDLC_X25)         += hdlc_x25.o
 
 pc300-y                                := pc300_drv.o
 pc300-$(CONFIG_PC300_MLPPP)    += pc300_tty.o
@@ -38,10 +37,6 @@ obj-$(CONFIG_CYCLADES_SYNC)  += cycx_drv.o cyclomx.o
 obj-$(CONFIG_LAPBETHER)                += lapbether.o
 obj-$(CONFIG_SBNI)             += sbni.o
 obj-$(CONFIG_PC300)            += pc300.o
-obj-$(CONFIG_HDLC)             += hdlc.o
-ifeq ($(CONFIG_HDLC_PPP),y)
-  obj-$(CONFIG_HDLC)           += syncppp.o
-endif
 obj-$(CONFIG_N2)               += n2.o
 obj-$(CONFIG_C101)             += c101.o
 obj-$(CONFIG_WANXL)            += wanxl.o
similarity index 67%
rename from drivers/net/wan/hdlc_generic.c
rename to drivers/net/wan/hdlc.c
index 04ca1f7b64247c2a2b2c09c9182ba6ab728a88cc..db354e0edbe57692185e1d6fecae60f7d5cfbbaa 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Generic HDLC support routines for Linux
  *
- * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -17,9 +17,9 @@
  * Use sethdlc utility to set line parameters, protocol and PVCs
  *
  * How does it work:
- * - proto.open(), close(), start(), stop() calls are serialized.
+ * - proto->open(), close(), start(), stop() calls are serialized.
  *   The order is: open, [ start, stop ... ] close ...
- * - proto.start() and stop() are called with spin_lock_irq held.
+ * - proto->start() and stop() are called with spin_lock_irq held.
  */
 
 #include <linux/module.h>
 #include <linux/hdlc.h>
 
 
-static const char* version = "HDLC support module revision 1.19";
+static const char* version = "HDLC support module revision 1.20";
 
 #undef DEBUG_LINK
 
+static struct hdlc_proto *first_proto = NULL;
+
 
 static int hdlc_change_mtu(struct net_device *dev, int new_mtu)
 {
@@ -63,11 +65,11 @@ static struct net_device_stats *hdlc_get_stats(struct net_device *dev)
 static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
                    struct packet_type *p, struct net_device *orig_dev)
 {
-       hdlc_device *hdlc = dev_to_hdlc(dev);
-       if (hdlc->proto.netif_rx)
-               return hdlc->proto.netif_rx(skb);
+       struct hdlc_device_desc *desc = dev_to_desc(dev);
+       if (desc->netif_rx)
+               return desc->netif_rx(skb);
 
-       hdlc->stats.rx_dropped++; /* Shouldn't happen */
+       desc->stats.rx_dropped++; /* Shouldn't happen */
        dev_kfree_skb(skb);
        return NET_RX_DROP;
 }
@@ -77,8 +79,8 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
 static inline void hdlc_proto_start(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       if (hdlc->proto.start)
-               return hdlc->proto.start(dev);
+       if (hdlc->proto->start)
+               return hdlc->proto->start(dev);
 }
 
 
@@ -86,8 +88,8 @@ static inline void hdlc_proto_start(struct net_device *dev)
 static inline void hdlc_proto_stop(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       if (hdlc->proto.stop)
-               return hdlc->proto.stop(dev);
+       if (hdlc->proto->stop)
+               return hdlc->proto->stop(dev);
 }
 
 
@@ -144,15 +146,15 @@ int hdlc_open(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
-       printk(KERN_DEBUG "hdlc_open() carrier %i open %i\n",
+       printk(KERN_DEBUG "%s: hdlc_open() carrier %i open %i\n", dev->name,
               hdlc->carrier, hdlc->open);
 #endif
 
-       if (hdlc->proto.id == -1)
+       if (hdlc->proto == NULL)
                return -ENOSYS; /* no protocol attached */
 
-       if (hdlc->proto.open) {
-               int result = hdlc->proto.open(dev);
+       if (hdlc->proto->open) {
+               int result = hdlc->proto->open(dev);
                if (result)
                        return result;
        }
@@ -178,7 +180,7 @@ void hdlc_close(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
-       printk(KERN_DEBUG "hdlc_close() carrier %i open %i\n",
+       printk(KERN_DEBUG "%s: hdlc_close() carrier %i open %i\n", dev->name,
               hdlc->carrier, hdlc->open);
 #endif
 
@@ -190,68 +192,34 @@ void hdlc_close(struct net_device *dev)
 
        spin_unlock_irq(&hdlc->state_lock);
 
-       if (hdlc->proto.close)
-               hdlc->proto.close(dev);
+       if (hdlc->proto->close)
+               hdlc->proto->close(dev);
 }
 
 
 
-#ifndef CONFIG_HDLC_RAW
-#define hdlc_raw_ioctl(dev, ifr)       -ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_RAW_ETH
-#define hdlc_raw_eth_ioctl(dev, ifr)   -ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_PPP
-#define hdlc_ppp_ioctl(dev, ifr)       -ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_CISCO
-#define hdlc_cisco_ioctl(dev, ifr)     -ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_FR
-#define hdlc_fr_ioctl(dev, ifr)                -ENOSYS
-#endif
-
-#ifndef CONFIG_HDLC_X25
-#define hdlc_x25_ioctl(dev, ifr)       -ENOSYS
-#endif
-
-
 int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-       hdlc_device *hdlc = dev_to_hdlc(dev);
-       unsigned int proto;
+       struct hdlc_proto *proto = first_proto;
+       int result;
 
        if (cmd != SIOCWANDEV)
                return -EINVAL;
 
-       switch(ifr->ifr_settings.type) {
-       case IF_PROTO_HDLC:
-       case IF_PROTO_HDLC_ETH:
-       case IF_PROTO_PPP:
-       case IF_PROTO_CISCO:
-       case IF_PROTO_FR:
-       case IF_PROTO_X25:
-               proto = ifr->ifr_settings.type;
-               break;
-
-       default:
-               proto = hdlc->proto.id;
+       if (dev_to_hdlc(dev)->proto) {
+               result = dev_to_hdlc(dev)->proto->ioctl(dev, ifr);
+               if (result != -EINVAL)
+                       return result;
        }
 
-       switch(proto) {
-       case IF_PROTO_HDLC:     return hdlc_raw_ioctl(dev, ifr);
-       case IF_PROTO_HDLC_ETH: return hdlc_raw_eth_ioctl(dev, ifr);
-       case IF_PROTO_PPP:      return hdlc_ppp_ioctl(dev, ifr);
-       case IF_PROTO_CISCO:    return hdlc_cisco_ioctl(dev, ifr);
-       case IF_PROTO_FR:       return hdlc_fr_ioctl(dev, ifr);
-       case IF_PROTO_X25:      return hdlc_x25_ioctl(dev, ifr);
-       default:                return -EINVAL;
+       /* Not handled by currently attached protocol (if any) */
+
+       while (proto) {
+               if ((result = proto->ioctl(dev, ifr)) != -EINVAL)
+                       return result;
+               proto = proto->next;
        }
+       return -EINVAL;
 }
 
 void hdlc_setup(struct net_device *dev)
@@ -267,8 +235,6 @@ void hdlc_setup(struct net_device *dev)
 
        dev->flags = IFF_POINTOPOINT | IFF_NOARP;
 
-       hdlc->proto.id = -1;
-       hdlc->proto.detach = NULL;
        hdlc->carrier = 1;
        hdlc->open = 0;
        spin_lock_init(&hdlc->state_lock);
@@ -277,7 +243,8 @@ void hdlc_setup(struct net_device *dev)
 struct net_device *alloc_hdlcdev(void *priv)
 {
        struct net_device *dev;
-       dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup);
+       dev = alloc_netdev(sizeof(struct hdlc_device_desc) +
+                          sizeof(hdlc_device), "hdlc%d", hdlc_setup);
        if (dev)
                dev_to_hdlc(dev)->priv = priv;
        return dev;
@@ -286,13 +253,71 @@ struct net_device *alloc_hdlcdev(void *priv)
 void unregister_hdlc_device(struct net_device *dev)
 {
        rtnl_lock();
-       hdlc_proto_detach(dev_to_hdlc(dev));
        unregister_netdevice(dev);
+       detach_hdlc_protocol(dev);
        rtnl_unlock();
 }
 
 
 
+int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
+                        int (*rx)(struct sk_buff *skb), size_t size)
+{
+       detach_hdlc_protocol(dev);
+
+       if (!try_module_get(proto->module))
+               return -ENOSYS;
+
+       if (size)
+               if ((dev_to_hdlc(dev)->state = kmalloc(size,
+                                                      GFP_KERNEL)) == NULL) {
+                       printk(KERN_WARNING "Memory squeeze on"
+                              " hdlc_proto_attach()\n");
+                       module_put(proto->module);
+                       return -ENOBUFS;
+               }
+       dev_to_hdlc(dev)->proto = proto;
+       dev_to_desc(dev)->netif_rx = rx;
+       return 0;
+}
+
+
+void detach_hdlc_protocol(struct net_device *dev)
+{
+       hdlc_device *hdlc = dev_to_hdlc(dev);
+
+       if (hdlc->proto) {
+               if (hdlc->proto->detach)
+                       hdlc->proto->detach(dev);
+               module_put(hdlc->proto->module);
+               hdlc->proto = NULL;
+       }
+       kfree(hdlc->state);
+       hdlc->state = NULL;
+}
+
+
+void register_hdlc_protocol(struct hdlc_proto *proto)
+{
+       proto->next = first_proto;
+       first_proto = proto;
+}
+
+
+void unregister_hdlc_protocol(struct hdlc_proto *proto)
+{
+       struct hdlc_proto **p = &first_proto;
+       while (*p) {
+               if (*p == proto) {
+                       *p = proto->next;
+                       return;
+               }
+               p = &((*p)->next);
+       }
+}
+
+
+
 MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
 MODULE_DESCRIPTION("HDLC support module");
 MODULE_LICENSE("GPL v2");
@@ -303,6 +328,10 @@ EXPORT_SYMBOL(hdlc_ioctl);
 EXPORT_SYMBOL(hdlc_setup);
 EXPORT_SYMBOL(alloc_hdlcdev);
 EXPORT_SYMBOL(unregister_hdlc_device);
+EXPORT_SYMBOL(register_hdlc_protocol);
+EXPORT_SYMBOL(unregister_hdlc_protocol);
+EXPORT_SYMBOL(attach_hdlc_protocol);
+EXPORT_SYMBOL(detach_hdlc_protocol);
 
 static struct packet_type hdlc_packet_type = {
        .type = __constant_htons(ETH_P_HDLC),
index f289daba0c7b308408d84ea209054859973e5773..7ec2b2f9b7eec6750c7906ff7f281b23bb530fe5 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * Cisco HDLC support
  *
- * Copyright (C) 2000 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 2000 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
 #define CISCO_KEEPALIVE_REQ    2       /* Cisco keepalive request */
 
 
+struct hdlc_header {
+       u8 address;
+       u8 control;
+       u16 protocol;
+}__attribute__ ((packed));
+
+
+struct cisco_packet {
+       u32 type;               /* code */
+       u32 par1;
+       u32 par2;
+       u16 rel;                /* reliability */
+       u32 time;
+}__attribute__ ((packed));
+#define        CISCO_PACKET_LEN        18
+#define        CISCO_BIG_PACKET_LEN    20
+
+
+struct cisco_state {
+       cisco_proto settings;
+
+       struct timer_list timer;
+       unsigned long last_poll;
+       int up;
+       int request_sent;
+       u32 txseq; /* TX sequence number */
+       u32 rxseq; /* RX sequence number */
+};
+
+
+static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr);
+
+
+static inline struct cisco_state * state(hdlc_device *hdlc)
+{
+       return(struct cisco_state *)(hdlc->state);
+}
+
+
 static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev,
                             u16 type, void *daddr, void *saddr,
                             unsigned int len)
 {
-       hdlc_header *data;
+       struct hdlc_header *data;
 #ifdef DEBUG_HARD_HEADER
        printk(KERN_DEBUG "%s: cisco_hard_header called\n", dev->name);
 #endif
 
-       skb_push(skb, sizeof(hdlc_header));
-       data = (hdlc_header*)skb->data;
+       skb_push(skb, sizeof(struct hdlc_header));
+       data = (struct hdlc_header*)skb->data;
        if (type == CISCO_KEEPALIVE)
                data->address = CISCO_MULTICAST;
        else
@@ -52,7 +91,7 @@ static int cisco_hard_header(struct sk_buff *skb, struct net_device *dev,
        data->control = 0;
        data->protocol = htons(type);
 
-       return sizeof(hdlc_header);
+       return sizeof(struct hdlc_header);
 }
 
 
@@ -61,9 +100,10 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
                                 u32 par1, u32 par2)
 {
        struct sk_buff *skb;
-       cisco_packet *data;
+       struct cisco_packet *data;
 
-       skb = dev_alloc_skb(sizeof(hdlc_header) + sizeof(cisco_packet));
+       skb = dev_alloc_skb(sizeof(struct hdlc_header) +
+                           sizeof(struct cisco_packet));
        if (!skb) {
                printk(KERN_WARNING
                       "%s: Memory squeeze on cisco_keepalive_send()\n",
@@ -72,7 +112,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
        }
        skb_reserve(skb, 4);
        cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0);
-       data = (cisco_packet*)(skb->data + 4);
+       data = (struct cisco_packet*)(skb->data + 4);
 
        data->type = htonl(type);
        data->par1 = htonl(par1);
@@ -81,7 +121,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
        /* we will need do_div here if 1000 % HZ != 0 */
        data->time = htonl((jiffies - INITIAL_JIFFIES) * (1000 / HZ));
 
-       skb_put(skb, sizeof(cisco_packet));
+       skb_put(skb, sizeof(struct cisco_packet));
        skb->priority = TC_PRIO_CONTROL;
        skb->dev = dev;
        skb->nh.raw = skb->data;
@@ -93,9 +133,9 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
 
 static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
-       hdlc_header *data = (hdlc_header*)skb->data;
+       struct hdlc_header *data = (struct hdlc_header*)skb->data;
 
-       if (skb->len < sizeof(hdlc_header))
+       if (skb->len < sizeof(struct hdlc_header))
                return __constant_htons(ETH_P_HDLC);
 
        if (data->address != CISCO_MULTICAST &&
@@ -106,7 +146,7 @@ static __be16 cisco_type_trans(struct sk_buff *skb, struct net_device *dev)
        case __constant_htons(ETH_P_IP):
        case __constant_htons(ETH_P_IPX):
        case __constant_htons(ETH_P_IPV6):
-               skb_pull(skb, sizeof(hdlc_header));
+               skb_pull(skb, sizeof(struct hdlc_header));
                return data->protocol;
        default:
                return __constant_htons(ETH_P_HDLC);
@@ -118,12 +158,12 @@ static int cisco_rx(struct sk_buff *skb)
 {
        struct net_device *dev = skb->dev;
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       hdlc_header *data = (hdlc_header*)skb->data;
-       cisco_packet *cisco_data;
+       struct hdlc_header *data = (struct hdlc_header*)skb->data;
+       struct cisco_packet *cisco_data;
        struct in_device *in_dev;
        u32 addr, mask;
 
-       if (skb->len < sizeof(hdlc_header))
+       if (skb->len < sizeof(struct hdlc_header))
                goto rx_error;
 
        if (data->address != CISCO_MULTICAST &&
@@ -137,15 +177,17 @@ static int cisco_rx(struct sk_buff *skb)
                return NET_RX_SUCCESS;
 
        case CISCO_KEEPALIVE:
-               if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN &&
-                   skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) {
-                       printk(KERN_INFO "%s: Invalid length of Cisco "
-                              "control packet (%d bytes)\n",
-                              dev->name, skb->len);
+               if ((skb->len != sizeof(struct hdlc_header) +
+                    CISCO_PACKET_LEN) &&
+                   (skb->len != sizeof(struct hdlc_header) +
+                    CISCO_BIG_PACKET_LEN)) {
+                       printk(KERN_INFO "%s: Invalid length of Cisco control"
+                              " packet (%d bytes)\n", dev->name, skb->len);
                        goto rx_error;
                }
 
-               cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header));
+               cisco_data = (struct cisco_packet*)(skb->data + sizeof
+                                                   (struct hdlc_header));
 
                switch(ntohl (cisco_data->type)) {
                case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
@@ -178,11 +220,11 @@ static int cisco_rx(struct sk_buff *skb)
                        goto rx_error;
 
                case CISCO_KEEPALIVE_REQ:
-                       hdlc->state.cisco.rxseq = ntohl(cisco_data->par1);
-                       if (hdlc->state.cisco.request_sent &&
-                           ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) {
-                               hdlc->state.cisco.last_poll = jiffies;
-                               if (!hdlc->state.cisco.up) {
+                       state(hdlc)->rxseq = ntohl(cisco_data->par1);
+                       if (state(hdlc)->request_sent &&
+                           ntohl(cisco_data->par2) == state(hdlc)->txseq) {
+                               state(hdlc)->last_poll = jiffies;
+                               if (!state(hdlc)->up) {
                                        u32 sec, min, hrs, days;
                                        sec = ntohl(cisco_data->time) / 1000;
                                        min = sec / 60; sec -= min * 60;
@@ -193,7 +235,7 @@ static int cisco_rx(struct sk_buff *skb)
                                               dev->name, days, hrs,
                                               min, sec);
                                        netif_dormant_off(dev);
-                                       hdlc->state.cisco.up = 1;
+                                       state(hdlc)->up = 1;
                                }
                        }
 
@@ -208,7 +250,7 @@ static int cisco_rx(struct sk_buff *skb)
        return NET_RX_DROP;
 
  rx_error:
-       hdlc->stats.rx_errors++; /* Mark error */
+       dev_to_desc(dev)->stats.rx_errors++; /* Mark error */
        dev_kfree_skb_any(skb);
        return NET_RX_DROP;
 }
@@ -220,23 +262,22 @@ static void cisco_timer(unsigned long arg)
        struct net_device *dev = (struct net_device *)arg;
        hdlc_device *hdlc = dev_to_hdlc(dev);
 
-       if (hdlc->state.cisco.up &&
-           time_after(jiffies, hdlc->state.cisco.last_poll +
-                      hdlc->state.cisco.settings.timeout * HZ)) {
-               hdlc->state.cisco.up = 0;
+       if (state(hdlc)->up &&
+           time_after(jiffies, state(hdlc)->last_poll +
+                      state(hdlc)->settings.timeout * HZ)) {
+               state(hdlc)->up = 0;
                printk(KERN_INFO "%s: Link down\n", dev->name);
                netif_dormant_on(dev);
        }
 
-       cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
-                            ++hdlc->state.cisco.txseq,
-                            hdlc->state.cisco.rxseq);
-       hdlc->state.cisco.request_sent = 1;
-       hdlc->state.cisco.timer.expires = jiffies +
-               hdlc->state.cisco.settings.interval * HZ;
-       hdlc->state.cisco.timer.function = cisco_timer;
-       hdlc->state.cisco.timer.data = arg;
-       add_timer(&hdlc->state.cisco.timer);
+       cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, ++state(hdlc)->txseq,
+                            state(hdlc)->rxseq);
+       state(hdlc)->request_sent = 1;
+       state(hdlc)->timer.expires = jiffies +
+               state(hdlc)->settings.interval * HZ;
+       state(hdlc)->timer.function = cisco_timer;
+       state(hdlc)->timer.data = arg;
+       add_timer(&state(hdlc)->timer);
 }
 
 
@@ -244,15 +285,15 @@ static void cisco_timer(unsigned long arg)
 static void cisco_start(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       hdlc->state.cisco.up = 0;
-       hdlc->state.cisco.request_sent = 0;
-       hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0;
-
-       init_timer(&hdlc->state.cisco.timer);
-       hdlc->state.cisco.timer.expires = jiffies + HZ; /*First poll after 1s*/
-       hdlc->state.cisco.timer.function = cisco_timer;
-       hdlc->state.cisco.timer.data = (unsigned long)dev;
-       add_timer(&hdlc->state.cisco.timer);
+       state(hdlc)->up = 0;
+       state(hdlc)->request_sent = 0;
+       state(hdlc)->txseq = state(hdlc)->rxseq = 0;
+
+       init_timer(&state(hdlc)->timer);
+       state(hdlc)->timer.expires = jiffies + HZ; /*First poll after 1s*/
+       state(hdlc)->timer.function = cisco_timer;
+       state(hdlc)->timer.data = (unsigned long)dev;
+       add_timer(&state(hdlc)->timer);
 }
 
 
@@ -260,15 +301,24 @@ static void cisco_start(struct net_device *dev)
 static void cisco_stop(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       del_timer_sync(&hdlc->state.cisco.timer);
+       del_timer_sync(&state(hdlc)->timer);
        netif_dormant_on(dev);
-       hdlc->state.cisco.up = 0;
-       hdlc->state.cisco.request_sent = 0;
+       state(hdlc)->up = 0;
+       state(hdlc)->request_sent = 0;
 }
 
 
 
-int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+       .start          = cisco_start,
+       .stop           = cisco_stop,
+       .type_trans     = cisco_type_trans,
+       .ioctl          = cisco_ioctl,
+       .module         = THIS_MODULE,
+};
+static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        cisco_proto __user *cisco_s = ifr->ifr_settings.ifs_ifsu.cisco;
        const size_t size = sizeof(cisco_proto);
@@ -278,12 +328,14 @@ int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto)
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_CISCO;
                if (ifr->ifr_settings.size < size) {
                        ifr->ifr_settings.size = size; /* data size wanted */
                        return -ENOBUFS;
                }
-               if (copy_to_user(cisco_s, &hdlc->state.cisco.settings, size))
+               if (copy_to_user(cisco_s, &state(hdlc)->settings, size))
                        return -EFAULT;
                return 0;
 
@@ -302,19 +354,15 @@ int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
                        return -EINVAL;
 
                result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
-
                if (result)
                        return result;
 
-               hdlc_proto_detach(hdlc);
-               memcpy(&hdlc->state.cisco.settings, &new_settings, size);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
+               result = attach_hdlc_protocol(dev, &proto, cisco_rx,
+                                             sizeof(struct cisco_state));
+               if (result)
+                       return result;
 
-               hdlc->proto.start = cisco_start;
-               hdlc->proto.stop = cisco_stop;
-               hdlc->proto.netif_rx = cisco_rx;
-               hdlc->proto.type_trans = cisco_type_trans;
-               hdlc->proto.id = IF_PROTO_CISCO;
+               memcpy(&state(hdlc)->settings, &new_settings, size);
                dev->hard_start_xmit = hdlc->xmit;
                dev->hard_header = cisco_hard_header;
                dev->hard_header_cache = NULL;
@@ -327,3 +375,25 @@ int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Cisco HDLC protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
index 7bb737bbdeb96cf09b1628e31b51c50c58f25372..b45ab680d2d624b52c4b44f4d1d51cb4c268de5d 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * Frame Relay support
  *
- * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -52,6 +52,8 @@
 #undef DEBUG_PKT
 #undef DEBUG_ECN
 #undef DEBUG_LINK
+#undef DEBUG_PROTO
+#undef DEBUG_PVC
 
 #define FR_UI                  0x03
 #define FR_PAD                 0x00
@@ -115,13 +117,53 @@ typedef struct {
 }__attribute__ ((packed)) fr_hdr;
 
 
+typedef struct pvc_device_struct {
+       struct net_device *frad;
+       struct net_device *main;
+       struct net_device *ether;       /* bridged Ethernet interface   */
+       struct pvc_device_struct *next; /* Sorted in ascending DLCI order */
+       int dlci;
+       int open_count;
+
+       struct {
+               unsigned int new: 1;
+               unsigned int active: 1;
+               unsigned int exist: 1;
+               unsigned int deleted: 1;
+               unsigned int fecn: 1;
+               unsigned int becn: 1;
+               unsigned int bandwidth; /* Cisco LMI reporting only */
+       }state;
+}pvc_device;
+
+
+struct frad_state {
+       fr_proto settings;
+       pvc_device *first_pvc;
+       int dce_pvc_count;
+
+       struct timer_list timer;
+       unsigned long last_poll;
+       int reliable;
+       int dce_changed;
+       int request;
+       int fullrep_sent;
+       u32 last_errors; /* last errors bit list */
+       u8 n391cnt;
+       u8 txseq; /* TX sequence number */
+       u8 rxseq; /* RX sequence number */
+};
+
+
+static int fr_ioctl(struct net_device *dev, struct ifreq *ifr);
+
+
 static inline u16 q922_to_dlci(u8 *hdr)
 {
        return ((hdr[0] & 0xFC) << 2) | ((hdr[1] & 0xF0) >> 4);
 }
 
 
-
 static inline void dlci_to_q922(u8 *hdr, u16 dlci)
 {
        hdr[0] = (dlci >> 2) & 0xFC;
@@ -129,10 +171,21 @@ static inline void dlci_to_q922(u8 *hdr, u16 dlci)
 }
 
 
+static inline struct frad_state * state(hdlc_device *hdlc)
+{
+       return(struct frad_state *)(hdlc->state);
+}
+
+
+static __inline__ pvc_device* dev_to_pvc(struct net_device *dev)
+{
+       return dev->priv;
+}
+
 
 static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
 {
-       pvc_device *pvc = hdlc->state.fr.first_pvc;
+       pvc_device *pvc = state(hdlc)->first_pvc;
 
        while (pvc) {
                if (pvc->dlci == dlci)
@@ -146,10 +199,10 @@ static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci)
 }
 
 
-static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci)
+static pvc_device* add_pvc(struct net_device *dev, u16 dlci)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc;
+       pvc_device *pvc, **pvc_p = &state(hdlc)->first_pvc;
 
        while (*pvc_p) {
                if ((*pvc_p)->dlci == dlci)
@@ -160,12 +213,15 @@ static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci)
        }
 
        pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC);
+#ifdef DEBUG_PVC
+       printk(KERN_DEBUG "add_pvc: allocated pvc %p, frad %p\n", pvc, dev);
+#endif
        if (!pvc)
                return NULL;
 
        memset(pvc, 0, sizeof(pvc_device));
        pvc->dlci = dlci;
-       pvc->master = dev;
+       pvc->frad = dev;
        pvc->next = *pvc_p;     /* Put it in the chain */
        *pvc_p = pvc;
        return pvc;
@@ -174,7 +230,7 @@ static inline pvc_device* add_pvc(struct net_device *dev, u16 dlci)
 
 static inline int pvc_is_used(pvc_device *pvc)
 {
-       return pvc->main != NULL || pvc->ether != NULL;
+       return pvc->main || pvc->ether;
 }
 
 
@@ -200,11 +256,14 @@ static inline void pvc_carrier(int on, pvc_device *pvc)
 
 static inline void delete_unused_pvcs(hdlc_device *hdlc)
 {
-       pvc_device **pvc_p = &hdlc->state.fr.first_pvc;
+       pvc_device **pvc_p = &state(hdlc)->first_pvc;
 
        while (*pvc_p) {
                if (!pvc_is_used(*pvc_p)) {
                        pvc_device *pvc = *pvc_p;
+#ifdef DEBUG_PVC
+                       printk(KERN_DEBUG "freeing unused pvc: %p\n", pvc);
+#endif
                        *pvc_p = pvc->next;
                        kfree(pvc);
                        continue;
@@ -295,16 +354,16 @@ static int pvc_open(struct net_device *dev)
 {
        pvc_device *pvc = dev_to_pvc(dev);
 
-       if ((pvc->master->flags & IFF_UP) == 0)
-               return -EIO;  /* Master must be UP in order to activate PVC */
+       if ((pvc->frad->flags & IFF_UP) == 0)
+               return -EIO;  /* Frad must be UP in order to activate PVC */
 
        if (pvc->open_count++ == 0) {
-               hdlc_device *hdlc = dev_to_hdlc(pvc->master);
-               if (hdlc->state.fr.settings.lmi == LMI_NONE)
-                       pvc->state.active = netif_carrier_ok(pvc->master);
+               hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
+               if (state(hdlc)->settings.lmi == LMI_NONE)
+                       pvc->state.active = netif_carrier_ok(pvc->frad);
 
                pvc_carrier(pvc->state.active, pvc);
-               hdlc->state.fr.dce_changed = 1;
+               state(hdlc)->dce_changed = 1;
        }
        return 0;
 }
@@ -316,12 +375,12 @@ static int pvc_close(struct net_device *dev)
        pvc_device *pvc = dev_to_pvc(dev);
 
        if (--pvc->open_count == 0) {
-               hdlc_device *hdlc = dev_to_hdlc(pvc->master);
-               if (hdlc->state.fr.settings.lmi == LMI_NONE)
+               hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
+               if (state(hdlc)->settings.lmi == LMI_NONE)
                        pvc->state.active = 0;
 
-               if (hdlc->state.fr.settings.dce) {
-                       hdlc->state.fr.dce_changed = 1;
+               if (state(hdlc)->settings.dce) {
+                       state(hdlc)->dce_changed = 1;
                        pvc->state.active = 0;
                }
        }
@@ -348,7 +407,7 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                }
 
                info.dlci = pvc->dlci;
-               memcpy(info.master, pvc->master->name, IFNAMSIZ);
+               memcpy(info.master, pvc->frad->name, IFNAMSIZ);
                if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info,
                                 &info, sizeof(info)))
                        return -EFAULT;
@@ -361,7 +420,7 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
 static inline struct net_device_stats *pvc_get_stats(struct net_device *dev)
 {
-       return netdev_priv(dev);
+       return &dev_to_desc(dev)->stats;
 }
 
 
@@ -393,7 +452,7 @@ static int pvc_xmit(struct sk_buff *skb, struct net_device *dev)
                        stats->tx_packets++;
                        if (pvc->state.fecn) /* TX Congestion counter */
                                stats->tx_compressed++;
-                       skb->dev = pvc->master;
+                       skb->dev = pvc->frad;
                        dev_queue_xmit(skb);
                        return 0;
                }
@@ -419,7 +478,7 @@ static int pvc_change_mtu(struct net_device *dev, int new_mtu)
 static inline void fr_log_dlci_active(pvc_device *pvc)
 {
        printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n",
-              pvc->master->name,
+              pvc->frad->name,
               pvc->dlci,
               pvc->main ? pvc->main->name : "",
               pvc->main && pvc->ether ? " " : "",
@@ -438,21 +497,20 @@ static inline u8 fr_lmi_nextseq(u8 x)
 }
 
 
-
 static void fr_lmi_send(struct net_device *dev, int fullrep)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
        struct sk_buff *skb;
-       pvc_device *pvc = hdlc->state.fr.first_pvc;
-       int lmi = hdlc->state.fr.settings.lmi;
-       int dce = hdlc->state.fr.settings.dce;
+       pvc_device *pvc = state(hdlc)->first_pvc;
+       int lmi = state(hdlc)->settings.lmi;
+       int dce = state(hdlc)->settings.dce;
        int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH;
        int stat_len = (lmi == LMI_CISCO) ? 6 : 3;
        u8 *data;
        int i = 0;
 
        if (dce && fullrep) {
-               len += hdlc->state.fr.dce_pvc_count * (2 + stat_len);
+               len += state(hdlc)->dce_pvc_count * (2 + stat_len);
                if (len > HDLC_MAX_MRU) {
                        printk(KERN_WARNING "%s: Too many PVCs while sending "
                               "LMI full report\n", dev->name);
@@ -486,8 +544,9 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
        data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY;
        data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE;
        data[i++] = LMI_INTEG_LEN;
-       data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq);
-       data[i++] = hdlc->state.fr.rxseq;
+       data[i++] = state(hdlc)->txseq =
+               fr_lmi_nextseq(state(hdlc)->txseq);
+       data[i++] = state(hdlc)->rxseq;
 
        if (dce && fullrep) {
                while (pvc) {
@@ -496,7 +555,7 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
                        data[i++] = stat_len;
 
                        /* LMI start/restart */
-                       if (hdlc->state.fr.reliable && !pvc->state.exist) {
+                       if (state(hdlc)->reliable && !pvc->state.exist) {
                                pvc->state.exist = pvc->state.new = 1;
                                fr_log_dlci_active(pvc);
                        }
@@ -541,15 +600,15 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
 static void fr_set_link_state(int reliable, struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       pvc_device *pvc = hdlc->state.fr.first_pvc;
+       pvc_device *pvc = state(hdlc)->first_pvc;
 
-       hdlc->state.fr.reliable = reliable;
+       state(hdlc)->reliable = reliable;
        if (reliable) {
                netif_dormant_off(dev);
-               hdlc->state.fr.n391cnt = 0; /* Request full status */
-               hdlc->state.fr.dce_changed = 1;
+               state(hdlc)->n391cnt = 0; /* Request full status */
+               state(hdlc)->dce_changed = 1;
 
-               if (hdlc->state.fr.settings.lmi == LMI_NONE) {
+               if (state(hdlc)->settings.lmi == LMI_NONE) {
                        while (pvc) {   /* Activate all PVCs */
                                pvc_carrier(1, pvc);
                                pvc->state.exist = pvc->state.active = 1;
@@ -563,7 +622,7 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
                        pvc_carrier(0, pvc);
                        pvc->state.exist = pvc->state.active = 0;
                        pvc->state.new = 0;
-                       if (!hdlc->state.fr.settings.dce)
+                       if (!state(hdlc)->settings.dce)
                                pvc->state.bandwidth = 0;
                        pvc = pvc->next;
                }
@@ -571,7 +630,6 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
 }
 
 
-
 static void fr_timer(unsigned long arg)
 {
        struct net_device *dev = (struct net_device *)arg;
@@ -579,62 +637,61 @@ static void fr_timer(unsigned long arg)
        int i, cnt = 0, reliable;
        u32 list;
 
-       if (hdlc->state.fr.settings.dce) {
-               reliable = hdlc->state.fr.request &&
-                       time_before(jiffies, hdlc->state.fr.last_poll +
-                                   hdlc->state.fr.settings.t392 * HZ);
-               hdlc->state.fr.request = 0;
+       if (state(hdlc)->settings.dce) {
+               reliable = state(hdlc)->request &&
+                       time_before(jiffies, state(hdlc)->last_poll +
+                                   state(hdlc)->settings.t392 * HZ);
+               state(hdlc)->request = 0;
        } else {
-               hdlc->state.fr.last_errors <<= 1; /* Shift the list */
-               if (hdlc->state.fr.request) {
-                       if (hdlc->state.fr.reliable)
+               state(hdlc)->last_errors <<= 1; /* Shift the list */
+               if (state(hdlc)->request) {
+                       if (state(hdlc)->reliable)
                                printk(KERN_INFO "%s: No LMI status reply "
                                       "received\n", dev->name);
-                       hdlc->state.fr.last_errors |= 1;
+                       state(hdlc)->last_errors |= 1;
                }
 
-               list = hdlc->state.fr.last_errors;
-               for (i = 0; i < hdlc->state.fr.settings.n393; i++, list >>= 1)
+               list = state(hdlc)->last_errors;
+               for (i = 0; i < state(hdlc)->settings.n393; i++, list >>= 1)
                        cnt += (list & 1);      /* errors count */
 
-               reliable = (cnt < hdlc->state.fr.settings.n392);
+               reliable = (cnt < state(hdlc)->settings.n392);
        }
 
-       if (hdlc->state.fr.reliable != reliable) {
+       if (state(hdlc)->reliable != reliable) {
                printk(KERN_INFO "%s: Link %sreliable\n", dev->name,
                       reliable ? "" : "un");
                fr_set_link_state(reliable, dev);
        }
 
-       if (hdlc->state.fr.settings.dce)
-               hdlc->state.fr.timer.expires = jiffies +
-                       hdlc->state.fr.settings.t392 * HZ;
+       if (state(hdlc)->settings.dce)
+               state(hdlc)->timer.expires = jiffies +
+                       state(hdlc)->settings.t392 * HZ;
        else {
-               if (hdlc->state.fr.n391cnt)
-                       hdlc->state.fr.n391cnt--;
+               if (state(hdlc)->n391cnt)
+                       state(hdlc)->n391cnt--;
 
-               fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0);
+               fr_lmi_send(dev, state(hdlc)->n391cnt == 0);
 
-               hdlc->state.fr.last_poll = jiffies;
-               hdlc->state.fr.request = 1;
-               hdlc->state.fr.timer.expires = jiffies +
-                       hdlc->state.fr.settings.t391 * HZ;
+               state(hdlc)->last_poll = jiffies;
+               state(hdlc)->request = 1;
+               state(hdlc)->timer.expires = jiffies +
+                       state(hdlc)->settings.t391 * HZ;
        }
 
-       hdlc->state.fr.timer.function = fr_timer;
-       hdlc->state.fr.timer.data = arg;
-       add_timer(&hdlc->state.fr.timer);
+       state(hdlc)->timer.function = fr_timer;
+       state(hdlc)->timer.data = arg;
+       add_timer(&state(hdlc)->timer);
 }
 
 
-
 static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
        pvc_device *pvc;
        u8 rxseq, txseq;
-       int lmi = hdlc->state.fr.settings.lmi;
-       int dce = hdlc->state.fr.settings.dce;
+       int lmi = state(hdlc)->settings.lmi;
+       int dce = state(hdlc)->settings.dce;
        int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i;
 
        if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
@@ -645,8 +702,8 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 
        if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
                             NLPID_CCITT_ANSI_LMI)) {
-               printk(KERN_INFO "%s: Received non-LMI frame with LMI"
-                      " DLCI\n", dev->name);
+               printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
+                      dev->name);
                return 1;
        }
 
@@ -706,53 +763,53 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
        }
        i++;
 
-       hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */
+       state(hdlc)->rxseq = skb->data[i++]; /* TX sequence from peer */
        rxseq = skb->data[i++]; /* Should confirm our sequence */
 
-       txseq = hdlc->state.fr.txseq;
+       txseq = state(hdlc)->txseq;
 
        if (dce)
-               hdlc->state.fr.last_poll = jiffies;
+               state(hdlc)->last_poll = jiffies;
 
        error = 0;
-       if (!hdlc->state.fr.reliable)
+       if (!state(hdlc)->reliable)
                error = 1;
 
-       if (rxseq == 0 || rxseq != txseq) {
-               hdlc->state.fr.n391cnt = 0; /* Ask for full report next time */
+       if (rxseq == 0 || rxseq != txseq) { /* Ask for full report next time */
+               state(hdlc)->n391cnt = 0;
                error = 1;
        }
 
        if (dce) {
-               if (hdlc->state.fr.fullrep_sent && !error) {
+               if (state(hdlc)->fullrep_sent && !error) {
 /* Stop sending full report - the last one has been confirmed by DTE */
-                       hdlc->state.fr.fullrep_sent = 0;
-                       pvc = hdlc->state.fr.first_pvc;
+                       state(hdlc)->fullrep_sent = 0;
+                       pvc = state(hdlc)->first_pvc;
                        while (pvc) {
                                if (pvc->state.new) {
                                        pvc->state.new = 0;
 
 /* Tell DTE that new PVC is now active */
-                                       hdlc->state.fr.dce_changed = 1;
+                                       state(hdlc)->dce_changed = 1;
                                }
                                pvc = pvc->next;
                        }
                }
 
-               if (hdlc->state.fr.dce_changed) {
+               if (state(hdlc)->dce_changed) {
                        reptype = LMI_FULLREP;
-                       hdlc->state.fr.fullrep_sent = 1;
-                       hdlc->state.fr.dce_changed = 0;
+                       state(hdlc)->fullrep_sent = 1;
+                       state(hdlc)->dce_changed = 0;
                }
 
-               hdlc->state.fr.request = 1; /* got request */
+               state(hdlc)->request = 1; /* got request */
                fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0);
                return 0;
        }
 
        /* DTE */
 
-       hdlc->state.fr.request = 0; /* got response, no request pending */
+       state(hdlc)->request = 0; /* got response, no request pending */
 
        if (error)
                return 0;
@@ -760,7 +817,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
        if (reptype != LMI_FULLREP)
                return 0;
 
-       pvc = hdlc->state.fr.first_pvc;
+       pvc = state(hdlc)->first_pvc;
 
        while (pvc) {
                pvc->state.deleted = 1;
@@ -827,7 +884,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
                i += stat_len;
        }
 
-       pvc = hdlc->state.fr.first_pvc;
+       pvc = state(hdlc)->first_pvc;
 
        while (pvc) {
                if (pvc->state.deleted && pvc->state.exist) {
@@ -841,17 +898,16 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
        }
 
        /* Next full report after N391 polls */
-       hdlc->state.fr.n391cnt = hdlc->state.fr.settings.n391;
+       state(hdlc)->n391cnt = state(hdlc)->settings.n391;
 
        return 0;
 }
 
 
-
 static int fr_rx(struct sk_buff *skb)
 {
-       struct net_device *ndev = skb->dev;
-       hdlc_device *hdlc = dev_to_hdlc(ndev);
+       struct net_device *frad = skb->dev;
+       hdlc_device *hdlc = dev_to_hdlc(frad);
        fr_hdr *fh = (fr_hdr*)skb->data;
        u8 *data = skb->data;
        u16 dlci;
@@ -864,11 +920,11 @@ static int fr_rx(struct sk_buff *skb)
        dlci = q922_to_dlci(skb->data);
 
        if ((dlci == LMI_CCITT_ANSI_DLCI &&
-            (hdlc->state.fr.settings.lmi == LMI_ANSI ||
-             hdlc->state.fr.settings.lmi == LMI_CCITT)) ||
+            (state(hdlc)->settings.lmi == LMI_ANSI ||
+             state(hdlc)->settings.lmi == LMI_CCITT)) ||
            (dlci == LMI_CISCO_DLCI &&
-            hdlc->state.fr.settings.lmi == LMI_CISCO)) {
-               if (fr_lmi_recv(ndev, skb))
+            state(hdlc)->settings.lmi == LMI_CISCO)) {
+               if (fr_lmi_recv(frad, skb))
                        goto rx_error;
                dev_kfree_skb_any(skb);
                return NET_RX_SUCCESS;
@@ -878,7 +934,7 @@ static int fr_rx(struct sk_buff *skb)
        if (!pvc) {
 #ifdef DEBUG_PKT
                printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n",
-                      ndev->name, dlci);
+                      frad->name, dlci);
 #endif
                dev_kfree_skb_any(skb);
                return NET_RX_DROP;
@@ -886,7 +942,7 @@ static int fr_rx(struct sk_buff *skb)
 
        if (pvc->state.fecn != fh->fecn) {
 #ifdef DEBUG_ECN
-               printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", ndev->name,
+               printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", frad->name,
                       dlci, fh->fecn ? "N" : "FF");
 #endif
                pvc->state.fecn ^= 1;
@@ -894,7 +950,7 @@ static int fr_rx(struct sk_buff *skb)
 
        if (pvc->state.becn != fh->becn) {
 #ifdef DEBUG_ECN
-               printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", ndev->name,
+               printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", frad->name,
                       dlci, fh->becn ? "N" : "FF");
 #endif
                pvc->state.becn ^= 1;
@@ -902,7 +958,7 @@ static int fr_rx(struct sk_buff *skb)
 
 
        if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
-               hdlc->stats.rx_dropped++;
+               dev_to_desc(frad)->stats.rx_dropped++;
                return NET_RX_DROP;
        }
 
@@ -938,13 +994,13 @@ static int fr_rx(struct sk_buff *skb)
 
                default:
                        printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
-                              "PID=%x\n", ndev->name, oui, pid);
+                              "PID=%x\n", frad->name, oui, pid);
                        dev_kfree_skb_any(skb);
                        return NET_RX_DROP;
                }
        } else {
                printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
-                      "length = %i\n", ndev->name, data[3], skb->len);
+                      "length = %i\n", frad->name, data[3], skb->len);
                dev_kfree_skb_any(skb);
                return NET_RX_DROP;
        }
@@ -964,7 +1020,7 @@ static int fr_rx(struct sk_buff *skb)
        }
 
  rx_error:
-       hdlc->stats.rx_errors++; /* Mark error */
+       dev_to_desc(frad)->stats.rx_errors++; /* Mark error */
        dev_kfree_skb_any(skb);
        return NET_RX_DROP;
 }
@@ -977,44 +1033,42 @@ static void fr_start(struct net_device *dev)
 #ifdef DEBUG_LINK
        printk(KERN_DEBUG "fr_start\n");
 #endif
-       if (hdlc->state.fr.settings.lmi != LMI_NONE) {
-               hdlc->state.fr.reliable = 0;
-               hdlc->state.fr.dce_changed = 1;
-               hdlc->state.fr.request = 0;
-               hdlc->state.fr.fullrep_sent = 0;
-               hdlc->state.fr.last_errors = 0xFFFFFFFF;
-               hdlc->state.fr.n391cnt = 0;
-               hdlc->state.fr.txseq = hdlc->state.fr.rxseq = 0;
-
-               init_timer(&hdlc->state.fr.timer);
+       if (state(hdlc)->settings.lmi != LMI_NONE) {
+               state(hdlc)->reliable = 0;
+               state(hdlc)->dce_changed = 1;
+               state(hdlc)->request = 0;
+               state(hdlc)->fullrep_sent = 0;
+               state(hdlc)->last_errors = 0xFFFFFFFF;
+               state(hdlc)->n391cnt = 0;
+               state(hdlc)->txseq = state(hdlc)->rxseq = 0;
+
+               init_timer(&state(hdlc)->timer);
                /* First poll after 1 s */
-               hdlc->state.fr.timer.expires = jiffies + HZ;
-               hdlc->state.fr.timer.function = fr_timer;
-               hdlc->state.fr.timer.data = (unsigned long)dev;
-               add_timer(&hdlc->state.fr.timer);
+               state(hdlc)->timer.expires = jiffies + HZ;
+               state(hdlc)->timer.function = fr_timer;
+               state(hdlc)->timer.data = (unsigned long)dev;
+               add_timer(&state(hdlc)->timer);
        } else
                fr_set_link_state(1, dev);
 }
 
 
-
 static void fr_stop(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
 #ifdef DEBUG_LINK
        printk(KERN_DEBUG "fr_stop\n");
 #endif
-       if (hdlc->state.fr.settings.lmi != LMI_NONE)
-               del_timer_sync(&hdlc->state.fr.timer);
+       if (state(hdlc)->settings.lmi != LMI_NONE)
+               del_timer_sync(&state(hdlc)->timer);
        fr_set_link_state(0, dev);
 }
 
 
-
 static void fr_close(struct net_device *dev)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
-       pvc_device *pvc = hdlc->state.fr.first_pvc;
+       pvc_device *pvc = state(hdlc)->first_pvc;
 
        while (pvc) {           /* Shutdown all PVCs for this FRAD */
                if (pvc->main)
@@ -1025,7 +1079,8 @@ static void fr_close(struct net_device *dev)
        }
 }
 
-static void dlci_setup(struct net_device *dev)
+
+static void pvc_setup(struct net_device *dev)
 {
        dev->type = ARPHRD_DLCI;
        dev->flags = IFF_POINTOPOINT;
@@ -1033,9 +1088,9 @@ static void dlci_setup(struct net_device *dev)
        dev->addr_len = 2;
 }
 
-static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
+static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
 {
-       hdlc_device *hdlc = dev_to_hdlc(master);
+       hdlc_device *hdlc = dev_to_hdlc(frad);
        pvc_device *pvc = NULL;
        struct net_device *dev;
        int result, used;
@@ -1044,9 +1099,9 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
        if (type == ARPHRD_ETHER)
                prefix = "pvceth%d";
 
-       if ((pvc = add_pvc(master, dlci)) == NULL) {
+       if ((pvc = add_pvc(frad, dlci)) == NULL) {
                printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n",
-                      master->name);
+                      frad->name);
                return -ENOBUFS;
        }
 
@@ -1060,11 +1115,11 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
                                   "pvceth%d", ether_setup);
        else
                dev = alloc_netdev(sizeof(struct net_device_stats),
-                                  "pvc%d", dlci_setup);
+                                  "pvc%d", pvc_setup);
 
        if (!dev) {
                printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n",
-                      master->name);
+                      frad->name);
                delete_unused_pvcs(hdlc);
                return -ENOBUFS;
        }
@@ -1102,8 +1157,8 @@ static int fr_add_pvc(struct net_device *master, unsigned int dlci, int type)
        dev->destructor = free_netdev;
        *get_dev_p(pvc, type) = dev;
        if (!used) {
-               hdlc->state.fr.dce_changed = 1;
-               hdlc->state.fr.dce_pvc_count++;
+               state(hdlc)->dce_changed = 1;
+               state(hdlc)->dce_pvc_count++;
        }
        return 0;
 }
@@ -1128,8 +1183,8 @@ static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
        *get_dev_p(pvc, type) = NULL;
 
        if (!pvc_is_used(pvc)) {
-               hdlc->state.fr.dce_pvc_count--;
-               hdlc->state.fr.dce_changed = 1;
+               state(hdlc)->dce_pvc_count--;
+               state(hdlc)->dce_changed = 1;
        }
        delete_unused_pvcs(hdlc);
        return 0;
@@ -1137,14 +1192,13 @@ static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type)
 
 
 
-static void fr_destroy(hdlc_device *hdlc)
+static void fr_destroy(struct net_device *frad)
 {
-       pvc_device *pvc;
-
-       pvc = hdlc->state.fr.first_pvc;
-       hdlc->state.fr.first_pvc = NULL; /* All PVCs destroyed */
-       hdlc->state.fr.dce_pvc_count = 0;
-       hdlc->state.fr.dce_changed = 1;
+       hdlc_device *hdlc = dev_to_hdlc(frad);
+       pvc_device *pvc = state(hdlc)->first_pvc;
+       state(hdlc)->first_pvc = NULL; /* All PVCs destroyed */
+       state(hdlc)->dce_pvc_count = 0;
+       state(hdlc)->dce_changed = 1;
 
        while (pvc) {
                pvc_device *next = pvc->next;
@@ -1161,8 +1215,17 @@ static void fr_destroy(hdlc_device *hdlc)
 }
 
 
+static struct hdlc_proto proto = {
+       .close          = fr_close,
+       .start          = fr_start,
+       .stop           = fr_stop,
+       .detach         = fr_destroy,
+       .ioctl          = fr_ioctl,
+       .module         = THIS_MODULE,
+};
+
 
-int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
+static int fr_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        fr_proto __user *fr_s = ifr->ifr_settings.ifs_ifsu.fr;
        const size_t size = sizeof(fr_proto);
@@ -1173,12 +1236,14 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_FR;
                if (ifr->ifr_settings.size < size) {
                        ifr->ifr_settings.size = size; /* data size wanted */
                        return -ENOBUFS;
                }
-               if (copy_to_user(fr_s, &hdlc->state.fr.settings, size))
+               if (copy_to_user(fr_s, &state(hdlc)->settings, size))
                        return -EFAULT;
                return 0;
 
@@ -1213,20 +1278,16 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
 
-               if (hdlc->proto.id != IF_PROTO_FR) {
-                       hdlc_proto_detach(hdlc);
-                       hdlc->state.fr.first_pvc = NULL;
-                       hdlc->state.fr.dce_pvc_count = 0;
+               if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */
+                       result = attach_hdlc_protocol(dev, &proto, fr_rx,
+                                                     sizeof(struct frad_state));
+                       if (result)
+                               return result;
+                       state(hdlc)->first_pvc = NULL;
+                       state(hdlc)->dce_pvc_count = 0;
                }
-               memcpy(&hdlc->state.fr.settings, &new_settings, size);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-               hdlc->proto.close = fr_close;
-               hdlc->proto.start = fr_start;
-               hdlc->proto.stop = fr_stop;
-               hdlc->proto.detach = fr_destroy;
-               hdlc->proto.netif_rx = fr_rx;
-               hdlc->proto.id = IF_PROTO_FR;
+               memcpy(&state(hdlc)->settings, &new_settings, size);
+
                dev->hard_start_xmit = hdlc->xmit;
                dev->hard_header = NULL;
                dev->type = ARPHRD_FRAD;
@@ -1238,6 +1299,9 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
        case IF_PROTO_FR_DEL_PVC:
        case IF_PROTO_FR_ADD_ETH_PVC:
        case IF_PROTO_FR_DEL_ETH_PVC:
+               if (dev_to_hdlc(dev)->proto != &proto) /* Different proto */
+                       return -EINVAL;
+
                if(!capable(CAP_NET_ADMIN))
                        return -EPERM;
 
@@ -1263,3 +1327,24 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Frame-Relay protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
index fbaab5bf71eb55b50ad8acc303dbad412d2776d9..e9f717070fde0d58bc4f1c103472510c7f9b9fff 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * Point-to-point protocol support
  *
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
 #include <linux/lapb.h>
 #include <linux/rtnetlink.h>
 #include <linux/hdlc.h>
+#include <net/syncppp.h>
+
+struct ppp_state {
+       struct ppp_device pppdev;
+       struct ppp_device *syncppp_ptr;
+       int (*old_change_mtu)(struct net_device *dev, int new_mtu);
+};
+
+static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr);
+
+
+static inline struct ppp_state* state(hdlc_device *hdlc)
+{
+       return(struct ppp_state *)(hdlc->state);
+}
 
 
 static int ppp_open(struct net_device *dev)
@@ -30,16 +45,16 @@ static int ppp_open(struct net_device *dev)
        void *old_ioctl;
        int result;
 
-       dev->priv = &hdlc->state.ppp.syncppp_ptr;
-       hdlc->state.ppp.syncppp_ptr = &hdlc->state.ppp.pppdev;
-       hdlc->state.ppp.pppdev.dev = dev;
+       dev->priv = &state(hdlc)->syncppp_ptr;
+       state(hdlc)->syncppp_ptr = &state(hdlc)->pppdev;
+       state(hdlc)->pppdev.dev = dev;
 
        old_ioctl = dev->do_ioctl;
-       hdlc->state.ppp.old_change_mtu = dev->change_mtu;
-       sppp_attach(&hdlc->state.ppp.pppdev);
+       state(hdlc)->old_change_mtu = dev->change_mtu;
+       sppp_attach(&state(hdlc)->pppdev);
        /* sppp_attach nukes them. We don't need syncppp's ioctl */
        dev->do_ioctl = old_ioctl;
-       hdlc->state.ppp.pppdev.sppp.pp_flags &= ~PP_CISCO;
+       state(hdlc)->pppdev.sppp.pp_flags &= ~PP_CISCO;
        dev->type = ARPHRD_PPP;
        result = sppp_open(dev);
        if (result) {
@@ -59,7 +74,7 @@ static void ppp_close(struct net_device *dev)
        sppp_close(dev);
        sppp_detach(dev);
        dev->rebuild_header = NULL;
-       dev->change_mtu = hdlc->state.ppp.old_change_mtu;
+       dev->change_mtu = state(hdlc)->old_change_mtu;
        dev->mtu = HDLC_MAX_MTU;
        dev->hard_header_len = 16;
 }
@@ -73,13 +88,24 @@ static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev)
 
 
 
-int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+       .open           = ppp_open,
+       .close          = ppp_close,
+       .type_trans     = ppp_type_trans,
+       .ioctl          = ppp_ioctl,
+       .module         = THIS_MODULE,
+};
+
+
+static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
        int result;
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto)
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_PPP;
                return 0; /* return protocol only, no settable parameters */
 
@@ -96,13 +122,10 @@ int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
 
-               hdlc_proto_detach(hdlc);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-               hdlc->proto.open = ppp_open;
-               hdlc->proto.close = ppp_close;
-               hdlc->proto.type_trans = ppp_type_trans;
-               hdlc->proto.id = IF_PROTO_PPP;
+               result = attach_hdlc_protocol(dev, &proto, NULL,
+                                             sizeof(struct ppp_state));
+               if (result)
+                       return result;
                dev->hard_start_xmit = hdlc->xmit;
                dev->hard_header = NULL;
                dev->type = ARPHRD_PPP;
@@ -113,3 +136,25 @@ int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("PPP protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
index f15aa6ba77f1ee8450fd6dabb35add9d637ef94a..fe3cae5c6b9d07a267fde91d3051c950ea11e906 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * HDLC support
  *
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -24,6 +24,8 @@
 #include <linux/hdlc.h>
 
 
+static int raw_ioctl(struct net_device *dev, struct ifreq *ifr);
+
 static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
        return __constant_htons(ETH_P_IP);
@@ -31,7 +33,14 @@ static __be16 raw_type_trans(struct sk_buff *skb, struct net_device *dev)
 
 
 
-int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+       .type_trans     = raw_type_trans,
+       .ioctl          = raw_ioctl,
+       .module         = THIS_MODULE,
+};
+
+
+static int raw_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
        const size_t size = sizeof(raw_hdlc_proto);
@@ -41,12 +50,14 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto)
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_HDLC;
                if (ifr->ifr_settings.size < size) {
                        ifr->ifr_settings.size = size; /* data size wanted */
                        return -ENOBUFS;
                }
-               if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size))
+               if (copy_to_user(raw_s, hdlc->state, size))
                        return -EFAULT;
                return 0;
 
@@ -71,12 +82,11 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
 
-               hdlc_proto_detach(hdlc);
-               memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-               hdlc->proto.type_trans = raw_type_trans;
-               hdlc->proto.id = IF_PROTO_HDLC;
+               result = attach_hdlc_protocol(dev, &proto, NULL,
+                                             sizeof(raw_hdlc_proto));
+               if (result)
+                       return result;
+               memcpy(hdlc->state, &new_settings, size);
                dev->hard_start_xmit = hdlc->xmit;
                dev->hard_header = NULL;
                dev->type = ARPHRD_RAWHDLC;
@@ -88,3 +98,25 @@ int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Raw HDLC protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
index d1884987f94e08efbf06cc41ec68785b29a6a332..1a69a9aaa9b95fae17ffc077a1d8100dd612f414 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * HDLC Ethernet emulation support
  *
- * Copyright (C) 2002-2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 2002-2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -25,6 +25,7 @@
 #include <linux/etherdevice.h>
 #include <linux/hdlc.h>
 
+static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr);
 
 static int eth_tx(struct sk_buff *skb, struct net_device *dev)
 {
@@ -44,7 +45,14 @@ static int eth_tx(struct sk_buff *skb, struct net_device *dev)
 }
 
 
-int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
+static struct hdlc_proto proto = {
+       .type_trans     = eth_type_trans,
+       .ioctl          = raw_eth_ioctl,
+       .module         = THIS_MODULE,
+};
+
+
+static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
        const size_t size = sizeof(raw_hdlc_proto);
@@ -56,12 +64,14 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto)
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_HDLC_ETH;
                if (ifr->ifr_settings.size < size) {
                        ifr->ifr_settings.size = size; /* data size wanted */
                        return -ENOBUFS;
                }
-               if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size))
+               if (copy_to_user(raw_s, hdlc->state, size))
                        return -EFAULT;
                return 0;
 
@@ -86,12 +96,11 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
 
-               hdlc_proto_detach(hdlc);
-               memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-               hdlc->proto.type_trans = eth_type_trans;
-               hdlc->proto.id = IF_PROTO_HDLC_ETH;
+               result = attach_hdlc_protocol(dev, &proto, NULL,
+                                             sizeof(raw_hdlc_proto));
+               if (result)
+                       return result;
+               memcpy(hdlc->state, &new_settings, size);
                dev->hard_start_xmit = eth_tx;
                old_ch_mtu = dev->change_mtu;
                old_qlen = dev->tx_queue_len;
@@ -106,3 +115,25 @@ int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("Ethernet encapsulation support for generic HDLC");
+MODULE_LICENSE("GPL v2");
index a867fb411f89b90d1219e2a05801b6b6ad8a9419..e4bb9f8ad4337e1cb34bb7b9835732119877c3b3 100644 (file)
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * X.25 support
  *
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -25,6 +25,8 @@
 
 #include <net/x25device.h>
 
+static int x25_ioctl(struct net_device *dev, struct ifreq *ifr);
+
 /* These functions are callbacks called by LAPB layer */
 
 static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
@@ -162,30 +164,39 @@ static void x25_close(struct net_device *dev)
 
 static int x25_rx(struct sk_buff *skb)
 {
-       hdlc_device *hdlc = dev_to_hdlc(skb->dev);
+       struct hdlc_device_desc *desc = dev_to_desc(skb->dev);
 
        if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
-               hdlc->stats.rx_dropped++;
+               desc->stats.rx_dropped++;
                return NET_RX_DROP;
        }
 
        if (lapb_data_received(skb->dev, skb) == LAPB_OK)
                return NET_RX_SUCCESS;
 
-       hdlc->stats.rx_errors++;
+       desc->stats.rx_errors++;
        dev_kfree_skb_any(skb);
        return NET_RX_DROP;
 }
 
 
+static struct hdlc_proto proto = {
+       .open           = x25_open,
+       .close          = x25_close,
+       .ioctl          = x25_ioctl,
+       .module         = THIS_MODULE,
+};
+
 
-int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr)
+static int x25_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
        int result;
 
        switch (ifr->ifr_settings.type) {
        case IF_GET_PROTO:
+               if (dev_to_hdlc(dev)->proto != &proto)
+                       return -EINVAL;
                ifr->ifr_settings.type = IF_PROTO_X25;
                return 0; /* return protocol only, no settable parameters */
 
@@ -200,14 +211,9 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr)
                if (result)
                        return result;
 
-               hdlc_proto_detach(hdlc);
-               memset(&hdlc->proto, 0, sizeof(hdlc->proto));
-
-               hdlc->proto.open = x25_open;
-               hdlc->proto.close = x25_close;
-               hdlc->proto.netif_rx = x25_rx;
-               hdlc->proto.type_trans = NULL;
-               hdlc->proto.id = IF_PROTO_X25;
+               if ((result = attach_hdlc_protocol(dev, &proto,
+                                                  x25_rx, 0)) != 0)
+                       return result;
                dev->hard_start_xmit = x25_xmit;
                dev->hard_header = NULL;
                dev->type = ARPHRD_X25;
@@ -218,3 +224,25 @@ int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr)
 
        return -EINVAL;
 }
+
+
+static int __init mod_init(void)
+{
+       register_hdlc_protocol(&proto);
+       return 0;
+}
+
+
+
+static void __exit mod_exit(void)
+{
+       unregister_hdlc_protocol(&proto);
+}
+
+
+module_init(mod_init);
+module_exit(mod_exit);
+
+MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
+MODULE_DESCRIPTION("X.25 protocol support for generic HDLC");
+MODULE_LICENSE("GPL v2");
index 2024b26b99e6e2728945af0c553455cb1bdaef9a..63e9fcf31fb8a1008a54a6fcdc691a228cb4cb8e 100644 (file)
 #define        _PC300_H
 
 #include <linux/hdlc.h>
+#include <net/syncppp.h>
 #include "hd64572.h"
 #include "pc300-falc-lh.h"
 
index 56e69403d178f27ec908b4aa4c4162d8d8ad66d0..8d9b959bf15bd12eb62db63f8c58af437b91f042 100644 (file)
@@ -2016,7 +2016,6 @@ static void sca_intr(pc300_t * card)
                        pc300ch_t *chan = &card->chan[ch];
                        pc300dev_t *d = &chan->d;
                        struct net_device *dev = d->dev;
-                       hdlc_device *hdlc = dev_to_hdlc(dev);
 
                        spin_lock(&card->card_lock);
 
@@ -2049,8 +2048,8 @@ static void sca_intr(pc300_t * card)
                                                        }
                                                        cpc_net_rx(dev);
                                                        /* Discard invalid frames */
-                                                       hdlc->stats.rx_errors++;
-                                                       hdlc->stats.rx_over_errors++;
+                                                       hdlc_stats(dev)->rx_errors++;
+                                                       hdlc_stats(dev)->rx_over_errors++;
                                                        chan->rx_first_bd = 0;
                                                        chan->rx_last_bd = N_DMA_RX_BUF - 1;
                                                        rx_dma_start(card, ch);
@@ -2116,8 +2115,8 @@ static void sca_intr(pc300_t * card)
                                                                                   card->hw.cpld_reg2) &
                                                                   ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));
                                                }
-                                               hdlc->stats.tx_errors++;
-                                               hdlc->stats.tx_fifo_errors++;
+                                               hdlc_stats(dev)->tx_errors++;
+                                               hdlc_stats(dev)->tx_fifo_errors++;
                                                sca_tx_intr(d);
                                        }
                                }
@@ -2534,7 +2533,6 @@ static int cpc_change_mtu(struct net_device *dev, int new_mtu)
 
 static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-       hdlc_device *hdlc = dev_to_hdlc(dev);
        pc300dev_t *d = (pc300dev_t *) dev->priv;
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300_t *card = (pc300_t *) chan->card;
@@ -2552,10 +2550,10 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                case SIOCGPC300CONF:
 #ifdef CONFIG_PC300_MLPPP
                        if (conf->proto != PC300_PROTO_MLPPP) {
-                               conf->proto = hdlc->proto.id;
+                               conf->proto = /* FIXME hdlc->proto.id */ 0;
                        }
 #else
-                       conf->proto = hdlc->proto.id;
+                       conf->proto = /* FIXME hdlc->proto.id */ 0;
 #endif
                        memcpy(&conf_aux.conf, conf, sizeof(pc300chconf_t));
                        memcpy(&conf_aux.hw, &card->hw, sizeof(pc300hw_t));
@@ -2588,12 +2586,12 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                                        }
                                } else {
                                        memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
-                                       hdlc->proto.id = conf->proto;
+                                       /* FIXME hdlc->proto.id = conf->proto; */
                                }
                        }
 #else
                        memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
-                       hdlc->proto.id = conf->proto;
+                       /* FIXME hdlc->proto.id = conf->proto; */
 #endif
                        return 0;
                case SIOCGPC300STATUS:
@@ -2606,7 +2604,7 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                case SIOCGPC300UTILSTATS:
                        {
                                if (!arg) {     /* clear statistics */
-                                       memset(&hdlc->stats, 0, sizeof(struct net_device_stats));
+                                       memset(hdlc_stats(dev), 0, sizeof(struct net_device_stats));
                                        if (card->hw.type == PC300_TE) {
                                                memset(&chan->falc, 0, sizeof(falc_t));
                                        }
@@ -2617,7 +2615,7 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                                        pc300stats.hw_type = card->hw.type;
                                        pc300stats.line_on = card->chan[ch].d.line_on;
                                        pc300stats.line_off = card->chan[ch].d.line_off;
-                                       memcpy(&pc300stats.gen_stats, &hdlc->stats,
+                                       memcpy(&pc300stats.gen_stats, hdlc_stats(dev),
                                               sizeof(struct net_device_stats));
                                        if (card->hw.type == PC300_TE)
                                                memcpy(&pc300stats.te_stats,&chan->falc,sizeof(falc_t));
@@ -3147,7 +3145,6 @@ static void cpc_closech(pc300dev_t * d)
 
 int cpc_open(struct net_device *dev)
 {
-       hdlc_device *hdlc = dev_to_hdlc(dev);
        pc300dev_t *d = (pc300dev_t *) dev->priv;
        struct ifreq ifr;
        int result;
@@ -3156,12 +3153,14 @@ int cpc_open(struct net_device *dev)
        printk("pc300: cpc_open");
 #endif
 
+#ifdef FIXME
        if (hdlc->proto.id == IF_PROTO_PPP) {
                d->if_ptr = &hdlc->state.ppp.pppdev;
        }
+#endif
 
        result = hdlc_open(dev);
-       if (hdlc->proto.id == IF_PROTO_PPP) {
+       if (/* FIXME hdlc->proto.id == IF_PROTO_PPP*/ 0) {
                dev->priv = d;
        }
        if (result) {
@@ -3176,7 +3175,6 @@ int cpc_open(struct net_device *dev)
 
 static int cpc_close(struct net_device *dev)
 {
-       hdlc_device *hdlc = dev_to_hdlc(dev);
        pc300dev_t *d = (pc300dev_t *) dev->priv;
        pc300ch_t *chan = (pc300ch_t *) d->chan;
        pc300_t *card = (pc300_t *) chan->card;
@@ -3193,7 +3191,7 @@ static int cpc_close(struct net_device *dev)
        CPC_UNLOCK(card, flags);
 
        hdlc_close(dev);
-       if (hdlc->proto.id == IF_PROTO_PPP) {
+       if (/* FIXME hdlc->proto.id == IF_PROTO_PPP*/ 0) {
                d->if_ptr = NULL;
        }
 #ifdef CONFIG_PC300_MLPPP
index bff04cba3fed03d77c4f82356fee11acc3ceb6df..ba737c6cebec643a6316a058a0ebc2e0f1ac7d72 100644 (file)
@@ -5868,7 +5868,7 @@ static int airo_set_essid(struct net_device *dev,
                int     index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
                /* Check the size of the string */
-               if(dwrq->length > IW_ESSID_MAX_SIZE+1) {
+               if(dwrq->length > IW_ESSID_MAX_SIZE) {
                        return -E2BIG ;
                }
                /* Check if index is valid */
@@ -5880,7 +5880,7 @@ static int airo_set_essid(struct net_device *dev,
                memset(SSID_rid.ssids[index].ssid, 0,
                       sizeof(SSID_rid.ssids[index].ssid));
                memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length);
-               SSID_rid.ssids[index].len = dwrq->length - 1;
+               SSID_rid.ssids[index].len = dwrq->length;
        }
        SSID_rid.len = sizeof(SSID_rid);
        /* Write it to the card */
@@ -5990,7 +5990,7 @@ static int airo_set_nick(struct net_device *dev,
        struct airo_info *local = dev->priv;
 
        /* Check the size of the string */
-       if(dwrq->length > 16 + 1) {
+       if(dwrq->length > 16) {
                return -E2BIG;
        }
        readConfigRid(local, 1);
@@ -6015,7 +6015,7 @@ static int airo_get_nick(struct net_device *dev,
        readConfigRid(local, 1);
        strncpy(extra, local->config.nodeName, 16);
        extra[16] = '\0';
-       dwrq->length = strlen(extra) + 1;
+       dwrq->length = strlen(extra);
 
        return 0;
 }
@@ -6767,9 +6767,9 @@ static int airo_set_retry(struct net_device *dev,
        }
        readConfigRid(local, 1);
        if(vwrq->flags & IW_RETRY_LIMIT) {
-               if(vwrq->flags & IW_RETRY_MAX)
+               if(vwrq->flags & IW_RETRY_LONG)
                        local->config.longRetryLimit = vwrq->value;
-               else if (vwrq->flags & IW_RETRY_MIN)
+               else if (vwrq->flags & IW_RETRY_SHORT)
                        local->config.shortRetryLimit = vwrq->value;
                else {
                        /* No modifier : set both */
@@ -6805,14 +6805,14 @@ static int airo_get_retry(struct net_device *dev,
        if((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
                vwrq->flags = IW_RETRY_LIFETIME;
                vwrq->value = (int)local->config.txLifetime * 1024;
-       } else if((vwrq->flags & IW_RETRY_MAX)) {
-               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+       } else if((vwrq->flags & IW_RETRY_LONG)) {
+               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                vwrq->value = (int)local->config.longRetryLimit;
        } else {
                vwrq->flags = IW_RETRY_LIMIT;
                vwrq->value = (int)local->config.shortRetryLimit;
                if((int)local->config.shortRetryLimit != (int)local->config.longRetryLimit)
-                       vwrq->flags |= IW_RETRY_MIN;
+                       vwrq->flags |= IW_RETRY_SHORT;
        }
 
        return 0;
@@ -6990,6 +6990,7 @@ static int airo_set_power(struct net_device *dev,
                        local->config.rmode |= RXMODE_BC_MC_ADDR;
                        set_bit (FLAG_COMMIT, &local->flags);
                case IW_POWER_ON:
+                       /* This is broken, fixme ;-) */
                        break;
                default:
                        return -EINVAL;
index 995c7bea5897e9727ad66275eafd048658ec570f..0fc267d626dc0c68630b28e4953415a671eb672a 100644 (file)
@@ -1656,13 +1656,13 @@ static int atmel_set_essid(struct net_device *dev,
                priv->connect_to_any_BSS = 0;
 
                /* Check the size of the string */
-               if (dwrq->length > MAX_SSID_LENGTH + 1)
+               if (dwrq->length > MAX_SSID_LENGTH)
                         return -E2BIG;
                if (index != 0)
                        return -EINVAL;
 
-               memcpy(priv->new_SSID, extra, dwrq->length - 1);
-               priv->new_SSID_size = dwrq->length - 1;
+               memcpy(priv->new_SSID, extra, dwrq->length);
+               priv->new_SSID_size = dwrq->length;
        }
 
        return -EINPROGRESS;
@@ -2120,9 +2120,9 @@ static int atmel_set_retry(struct net_device *dev,
        struct atmel_private *priv = netdev_priv(dev);
 
        if (!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) {
-               if (vwrq->flags & IW_RETRY_MAX)
+               if (vwrq->flags & IW_RETRY_LONG)
                        priv->long_retry = vwrq->value;
-               else if (vwrq->flags & IW_RETRY_MIN)
+               else if (vwrq->flags & IW_RETRY_SHORT)
                        priv->short_retry = vwrq->value;
                else {
                        /* No modifier : set both */
@@ -2144,15 +2144,15 @@ static int atmel_get_retry(struct net_device *dev,
 
        vwrq->disabled = 0;      /* Can't be disabled */
 
-       /* Note : by default, display the min retry number */
-       if (vwrq->flags & IW_RETRY_MAX) {
-               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+       /* Note : by default, display the short retry number */
+       if (vwrq->flags & IW_RETRY_LONG) {
+               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                vwrq->value = priv->long_retry;
        } else {
                vwrq->flags = IW_RETRY_LIMIT;
                vwrq->value = priv->short_retry;
                if (priv->long_retry != priv->short_retry)
-                       vwrq->flags |= IW_RETRY_MIN;
+                       vwrq->flags |= IW_RETRY_SHORT;
        }
 
        return 0;
index 6d4ea36bc5644753b8933deedb8222ca83afc957..d6a8bf09878e8716ec8a0d2c053979b841b1e450 100644 (file)
@@ -666,7 +666,6 @@ struct bcm43xx_noise_calculation {
 };
 
 struct bcm43xx_stats {
-       u8 link_quality;
        u8 noise;
        struct iw_statistics wstats;
        /* Store the last TX/RX times here for updating the leds. */
index 923275ea0789aa6e26b031a74b521b64f2ce7eb2..b9df06a06ea96105f3a033c3a54377229ee6c66e 100644 (file)
@@ -54,7 +54,7 @@ static ssize_t write_file_dummy(struct file *file, const char __user *buf,
 
 static int open_file_generic(struct inode *inode, struct file *file)
 {
-       file->private_data = inode->u.generic_ip;
+       file->private_data = inode->i_private;
        return 0;
 }
 
index cb9a3ae8463a99ddacc77b4dabed99e81be7c3dd..eb65db7393ba56dc47d6dcc4c565cbab13042078 100644 (file)
@@ -2405,9 +2405,10 @@ static int bcm43xx_chip_init(struct bcm43xx_private *bcm)
                                   BCM43xx_UCODE_TIME) & 0x1f);
 
        if ( value16 > 0x128 ) {
-               dprintk(KERN_ERR PFX
-                       "Firmware: no support for microcode rev > 0x128\n");
-               err = -1;
+               printk(KERN_ERR PFX
+                       "Firmware: no support for microcode extracted "
+                       "from version 4.x binary drivers.\n");
+               err = -EOPNOTSUPP;
                goto err_release_fw;
        }
 
@@ -3169,8 +3170,7 @@ static void bcm43xx_periodic_work_handler(void *d)
                 * be preemtible.
                 */
                mutex_lock(&bcm->mutex);
-               netif_stop_queue(bcm->net_dev);
-               synchronize_net();
+               netif_tx_disable(bcm->net_dev);
                spin_lock_irqsave(&bcm->irq_lock, flags);
                bcm43xx_mac_suspend(bcm);
                if (bcm43xx_using_pio(bcm))
index eafd0f6626862ab5916f8ddd9906fd2e0b3c2450..52ce2a9334fb12eee4fa0d831950b04ea3128178 100644 (file)
@@ -361,7 +361,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
        if (phy->rev <= 2)
                for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
                        bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]);
-       else if ((phy->rev == 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
+       else if ((phy->rev >= 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200))
                for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++)
                        bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]);
        else
@@ -371,7 +371,7 @@ static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm)
        if (phy->rev == 2)
                for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
                        bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]);
-       else if ((phy->rev > 2) && (phy->rev <= 7))
+       else if ((phy->rev > 2) && (phy->rev <= 8))
                for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++)
                        bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]);
        
@@ -1197,7 +1197,7 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
 
        if (phy->rev == 1)
                bcm43xx_phy_initb5(bcm);
-       else if (phy->rev >= 2 && phy->rev <= 7)
+       else
                bcm43xx_phy_initb6(bcm);
        if (phy->rev >= 2 || phy->connected)
                bcm43xx_phy_inita(bcm);
@@ -1241,23 +1241,22 @@ static void bcm43xx_phy_initg(struct bcm43xx_private *bcm)
                bcm43xx_phy_lo_g_measure(bcm);
        } else {
                if (radio->version == 0x2050 && radio->revision == 8) {
-                       //FIXME
+                       bcm43xx_radio_write16(bcm, 0x0052,
+                                             (radio->txctl1 << 4) | radio->txctl2);
                } else {
                        bcm43xx_radio_write16(bcm, 0x0052,
                                              (bcm43xx_radio_read16(bcm, 0x0052)
                                               & 0xFFF0) | radio->txctl1);
                }
                if (phy->rev >= 6) {
-                       /*
                        bcm43xx_phy_write(bcm, 0x0036,
                                          (bcm43xx_phy_read(bcm, 0x0036)
-                                          & 0xF000) | (FIXME << 12));
-                       */
+                                          & 0xF000) | (radio->txctl2 << 12));
                }
                if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL)
                        bcm43xx_phy_write(bcm, 0x002E, 0x8075);
                else
-                       bcm43xx_phy_write(bcm, 0x003E, 0x807F);
+                       bcm43xx_phy_write(bcm, 0x002E, 0x807F);
                if (phy->rev < 2)
                        bcm43xx_phy_write(bcm, 0x002F, 0x0101);
                else
index 888077fc14c457b7082e706d503754efc9b46ab3..9b7b15cf656153b20d99633019b1885a1b87513c 100644 (file)
@@ -334,7 +334,7 @@ static int bcm43xx_wx_get_nick(struct net_device *net_dev,
        size_t len;
 
        mutex_lock(&bcm->mutex);
-       len = strlen(bcm->nick) + 1;
+       len = strlen(bcm->nick);
        memcpy(extra, bcm->nick, len);
        data->data.length = (__u16)len;
        data->data.flags = 1;
index c0efbfe605a5a20d3996a5f173a9e4657aac3dde..0159e4e93201cd2d7581d0d9ea2641c334948edd 100644 (file)
@@ -496,15 +496,14 @@ int bcm43xx_rx(struct bcm43xx_private *bcm,
        stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm,
                                              !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ),
                                              !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ));
-//TODO stats.noise = 
+       stats.noise = bcm->stats.noise;
        if (is_ofdm)
                stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp);
        else
                stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp);
        stats.received_channel = radio->channel;
-//TODO stats.control = 
        stats.mask = IEEE80211_STATMASK_SIGNAL |
-//TODO              IEEE80211_STATMASK_NOISE |
+                    IEEE80211_STATMASK_NOISE |
                     IEEE80211_STATMASK_RATE |
                     IEEE80211_STATMASK_RSSI;
        if (phy->type == BCM43xx_PHYTYPE_A)
index 7a4978516eac1e6ae3824beef4083ebe26007ae7..d061fb3443ff9ea614af960986adcc44930f2794 100644 (file)
@@ -1412,9 +1412,9 @@ static int prism2_ioctl_siwretry(struct net_device *dev,
        /* what could be done, if firmware would support this.. */
 
        if (rrq->flags & IW_RETRY_LIMIT) {
-               if (rrq->flags & IW_RETRY_MAX)
+               if (rrq->flags & IW_RETRY_LONG)
                        HFA384X_RID_LONGRETRYLIMIT = rrq->value;
-               else if (rrq->flags & IW_RETRY_MIN)
+               else if (rrq->flags & IW_RETRY_SHORT)
                        HFA384X_RID_SHORTRETRYLIMIT = rrq->value;
                else {
                        HFA384X_RID_LONGRETRYLIMIT = rrq->value;
@@ -1468,14 +1468,14 @@ static int prism2_ioctl_giwretry(struct net_device *dev,
                                rrq->value = le16_to_cpu(altretry);
                        else
                                rrq->value = local->manual_retry_count;
-               } else if ((rrq->flags & IW_RETRY_MAX)) {
-                       rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+               } else if ((rrq->flags & IW_RETRY_LONG)) {
+                       rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                        rrq->value = longretry;
                } else {
                        rrq->flags = IW_RETRY_LIMIT;
                        rrq->value = shortretry;
                        if (shortretry != longretry)
-                               rrq->flags |= IW_RETRY_MIN;
+                               rrq->flags |= IW_RETRY_SHORT;
                }
        }
        return 0;
index b4d81a04c89570454fc01ecb7a0a978c9d0ea908..6c5add701a6fc9508bdcc34d2b44587c17e882b4 100644 (file)
@@ -6958,7 +6958,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
        }
 
        if (wrqu->essid.flags && wrqu->essid.length) {
-               length = wrqu->essid.length - 1;
+               length = wrqu->essid.length;
                essid = extra;
        }
 
@@ -7051,7 +7051,7 @@ static int ipw2100_wx_get_nick(struct net_device *dev,
 
        struct ipw2100_priv *priv = ieee80211_priv(dev);
 
-       wrqu->data.length = strlen(priv->nick) + 1;
+       wrqu->data.length = strlen(priv->nick);
        memcpy(extra, priv->nick, wrqu->data.length);
        wrqu->data.flags = 1;   /* active */
 
@@ -7343,14 +7343,14 @@ static int ipw2100_wx_set_retry(struct net_device *dev,
                goto done;
        }
 
-       if (wrqu->retry.flags & IW_RETRY_MIN) {
+       if (wrqu->retry.flags & IW_RETRY_SHORT) {
                err = ipw2100_set_short_retry(priv, wrqu->retry.value);
                IPW_DEBUG_WX("SET Short Retry Limit -> %d \n",
                             wrqu->retry.value);
                goto done;
        }
 
-       if (wrqu->retry.flags & IW_RETRY_MAX) {
+       if (wrqu->retry.flags & IW_RETRY_LONG) {
                err = ipw2100_set_long_retry(priv, wrqu->retry.value);
                IPW_DEBUG_WX("SET Long Retry Limit -> %d \n",
                             wrqu->retry.value);
@@ -7383,14 +7383,14 @@ static int ipw2100_wx_get_retry(struct net_device *dev,
        if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME)
                return -EINVAL;
 
-       if (wrqu->retry.flags & IW_RETRY_MAX) {
-               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+       if (wrqu->retry.flags & IW_RETRY_LONG) {
+               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                wrqu->retry.value = priv->long_retry_limit;
        } else {
                wrqu->retry.flags =
                    (priv->short_retry_limit !=
                     priv->long_retry_limit) ?
-                   IW_RETRY_LIMIT | IW_RETRY_MIN : IW_RETRY_LIMIT;
+                   IW_RETRY_LIMIT | IW_RETRY_SHORT : IW_RETRY_LIMIT;
 
                wrqu->retry.value = priv->short_retry_limit;
        }
index 7358664e09088e53a2a92e1c78cbccdae96c02c9..5685d7ba55bb83c7758f3d8362dbc84a3797c89d 100644 (file)
@@ -8875,8 +8875,6 @@ static int ipw_wx_set_essid(struct net_device *dev,
         }
 
        length = min((int)wrqu->essid.length, IW_ESSID_MAX_SIZE);
-       if (!extra[length - 1])
-               length--;
 
        priv->config |= CFG_STATIC_ESSID;
 
@@ -8953,7 +8951,7 @@ static int ipw_wx_get_nick(struct net_device *dev,
        struct ipw_priv *priv = ieee80211_priv(dev);
        IPW_DEBUG_WX("Getting nick\n");
        mutex_lock(&priv->mutex);
-       wrqu->data.length = strlen(priv->nick) + 1;
+       wrqu->data.length = strlen(priv->nick);
        memcpy(extra, priv->nick, wrqu->data.length);
        wrqu->data.flags = 1;   /* active */
        mutex_unlock(&priv->mutex);
@@ -9276,9 +9274,9 @@ static int ipw_wx_set_retry(struct net_device *dev,
                return -EINVAL;
 
        mutex_lock(&priv->mutex);
-       if (wrqu->retry.flags & IW_RETRY_MIN)
+       if (wrqu->retry.flags & IW_RETRY_SHORT)
                priv->short_retry_limit = (u8) wrqu->retry.value;
-       else if (wrqu->retry.flags & IW_RETRY_MAX)
+       else if (wrqu->retry.flags & IW_RETRY_LONG)
                priv->long_retry_limit = (u8) wrqu->retry.value;
        else {
                priv->short_retry_limit = (u8) wrqu->retry.value;
@@ -9307,11 +9305,11 @@ static int ipw_wx_get_retry(struct net_device *dev,
                return -EINVAL;
        }
 
-       if (wrqu->retry.flags & IW_RETRY_MAX) {
-               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+       if (wrqu->retry.flags & IW_RETRY_LONG) {
+               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                wrqu->retry.value = priv->long_retry_limit;
-       } else if (wrqu->retry.flags & IW_RETRY_MIN) {
-               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
+       } else if (wrqu->retry.flags & IW_RETRY_SHORT) {
+               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
                wrqu->retry.value = priv->short_retry_limit;
        } else {
                wrqu->retry.flags = IW_RETRY_LIMIT;
index 1840b69e3cb5a6c5c5dfd3a04d239d50ac335442..9e19a963febc8b081839a9d9ca9216beb2942a6f 100644 (file)
@@ -3037,7 +3037,7 @@ static int orinoco_ioctl_getessid(struct net_device *dev,
        }
 
        erq->flags = 1;
-       erq->length = strlen(essidbuf) + 1;
+       erq->length = strlen(essidbuf);
 
        return 0;
 }
@@ -3078,7 +3078,7 @@ static int orinoco_ioctl_getnick(struct net_device *dev,
        memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1);
        orinoco_unlock(priv, &flags);
 
-       nrq->length = strlen(nickbuf)+1;
+       nrq->length = strlen(nickbuf);
 
        return 0;
 }
@@ -3575,14 +3575,14 @@ static int orinoco_ioctl_getretry(struct net_device *dev,
                rrq->value = lifetime * 1000;   /* ??? */
        } else {
                /* By default, display the min number */
-               if ((rrq->flags & IW_RETRY_MAX)) {
-                       rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+               if ((rrq->flags & IW_RETRY_LONG)) {
+                       rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                        rrq->value = long_limit;
                } else {
                        rrq->flags = IW_RETRY_LIMIT;
                        rrq->value = short_limit;
                        if(short_limit != long_limit)
-                               rrq->flags |= IW_RETRY_MIN;
+                               rrq->flags |= IW_RETRY_SHORT;
                }
        }
 
index c09fbf733b3a5ae8a8147ef63bb84f077aa161c4..286325ca3293d491f3005aa1f726ca0775645f78 100644 (file)
@@ -742,9 +742,9 @@ prism54_set_essid(struct net_device *ndev, struct iw_request_info *info,
 
        /* Check if we were asked for `any' */
        if (dwrq->flags && dwrq->length) {
-               if (dwrq->length > min(33, IW_ESSID_MAX_SIZE + 1))
+               if (dwrq->length > 32)
                        return -E2BIG;
-               essid.length = dwrq->length - 1;
+               essid.length = dwrq->length;
                memcpy(essid.octets, extra, dwrq->length);
        } else
                essid.length = 0;
@@ -814,7 +814,7 @@ prism54_get_nick(struct net_device *ndev, struct iw_request_info *info,
        dwrq->length = 0;
 
        down_read(&priv->mib_sem);
-       dwrq->length = strlen(priv->nickname) + 1;
+       dwrq->length = strlen(priv->nickname);
        memcpy(extra, priv->nickname, dwrq->length);
        up_read(&priv->mib_sem);
 
@@ -992,9 +992,9 @@ prism54_set_retry(struct net_device *ndev, struct iw_request_info *info,
                return -EINVAL;
 
        if (vwrq->flags & IW_RETRY_LIMIT) {
-               if (vwrq->flags & IW_RETRY_MIN)
+               if (vwrq->flags & IW_RETRY_SHORT)
                        slimit = vwrq->value;
-               else if (vwrq->flags & IW_RETRY_MAX)
+               else if (vwrq->flags & IW_RETRY_LONG)
                        llimit = vwrq->value;
                else {
                        /* we are asked to set both */
@@ -1035,18 +1035,18 @@ prism54_get_retry(struct net_device *ndev, struct iw_request_info *info,
                    mgt_get_request(priv, DOT11_OID_MAXTXLIFETIME, 0, NULL, &r);
                vwrq->value = r.u * 1024;
                vwrq->flags = IW_RETRY_LIFETIME;
-       } else if ((vwrq->flags & IW_RETRY_MAX)) {
+       } else if ((vwrq->flags & IW_RETRY_LONG)) {
                /* we are asked for the long retry limit */
                rvalue |=
                    mgt_get_request(priv, DOT11_OID_LONGRETRIES, 0, NULL, &r);
                vwrq->value = r.u;
-               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
        } else {
                /* default. get the  short retry limit */
                rvalue |=
                    mgt_get_request(priv, DOT11_OID_SHORTRETRIES, 0, NULL, &r);
                vwrq->value = r.u;
-               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
+               vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
        }
 
        return rvalue;
index 4574290f971fe0aeb6f39b81d83dde7684f15936..e82548ea609ac100f7310e81c8e7acdb4a946840 100644 (file)
@@ -1173,7 +1173,7 @@ static int ray_set_essid(struct net_device *dev,
                return -EOPNOTSUPP;
        } else {
                /* Check the size of the string */
-               if(dwrq->length > IW_ESSID_MAX_SIZE + 1) {
+               if(dwrq->length > IW_ESSID_MAX_SIZE) {
                        return -E2BIG;
                }
 
index e0d294c12970fb7f29c68927f67a2ecc6425b390..e3ae5f60d5bea0bc537a38e84cf0182f7280d8c9 100644 (file)
@@ -1802,15 +1802,15 @@ static int wl3501_get_retry(struct net_device *dev,
                                      &retry, sizeof(retry));
        if (rc)
                goto out;
-       if (wrqu->retry.flags & IW_RETRY_MAX) {
-               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+       if (wrqu->retry.flags & IW_RETRY_LONG) {
+               wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
                goto set_value;
        }
        rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_SHORT_RETRY_LIMIT,
                                  &retry, sizeof(retry));
        if (rc)
                goto out;
-       wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
+       wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
 set_value:
        wrqu->retry.value = retry;
        wrqu->retry.disabled = 0;
index c52e9bcf8d02f3fc688de9d7f1c17c49b51c9288..80af9a9fcbb33cd3f54614019b8511a6b8d6f579 100644 (file)
@@ -119,7 +119,7 @@ static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
        switch(urb->status) {
                case -EILSEQ:
                case -ENODEV:
-               case -ETIMEDOUT:
+               case -ETIME:
                case -ENOENT:
                case -EPIPE:
                case -EOVERFLOW:
@@ -201,7 +201,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
        switch(urb->status) {
                case -EILSEQ:
                case -ENODEV:
-               case -ETIMEDOUT:
+               case -ETIME:
                case -ENOENT:
                case -EPIPE:
                case -EOVERFLOW:
@@ -1218,7 +1218,7 @@ static int zd1201_set_essid(struct net_device *dev,
                return -EINVAL;
        if (data->length < 1)
                data->length = 1;
-       zd->essidlen = data->length-1;
+       zd->essidlen = data->length;
        memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1);
        memcpy(zd->essid, essid, data->length);
        return zd1201_join(zd, zd->essid, zd->essidlen);
index 7c4e32cf0d471d2ebf0b1496e6eb520285900f18..aa661b2b76c7c3c9b358ac296ee2806cb23743b3 100644 (file)
@@ -249,7 +249,6 @@ int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value)
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_ioread16_locked(chip, value, addr);
        mutex_unlock(&chip->mutex);
@@ -260,7 +259,6 @@ int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value)
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_ioread32_locked(chip, value, addr);
        mutex_unlock(&chip->mutex);
@@ -271,7 +269,6 @@ int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value)
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_iowrite16_locked(chip, value, addr);
        mutex_unlock(&chip->mutex);
@@ -282,7 +279,6 @@ int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value)
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_iowrite32_locked(chip, value, addr);
        mutex_unlock(&chip->mutex);
@@ -294,7 +290,6 @@ int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses,
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_ioread32v_locked(chip, values, addresses, count);
        mutex_unlock(&chip->mutex);
@@ -306,7 +301,6 @@ int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
 {
        int r;
 
-       ZD_ASSERT(!mutex_is_locked(&chip->mutex));
        mutex_lock(&chip->mutex);
        r = zd_iowrite32a_locked(chip, ioreqs, count);
        mutex_unlock(&chip->mutex);
@@ -331,13 +325,22 @@ static int read_pod(struct zd_chip *chip, u8 *rf_type)
        chip->patch_cr157 = (value >> 13) & 0x1;
        chip->patch_6m_band_edge = (value >> 21) & 0x1;
        chip->new_phy_layout = (value >> 31) & 0x1;
+       chip->link_led = ((value >> 4) & 1) ? LED1 : LED2;
+       chip->supports_tx_led = 1;
+       if (value & (1 << 24)) { /* LED scenario */
+               if (value & (1 << 29))
+                       chip->supports_tx_led = 0;
+       }
 
        dev_dbg_f(zd_chip_dev(chip),
                "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d "
-               "patch 6M %d new PHY %d\n",
+               "patch 6M %d new PHY %d link LED%d tx led %d\n",
                zd_rf_name(*rf_type), *rf_type,
                chip->pa_type, chip->patch_cck_gain,
-               chip->patch_cr157, chip->patch_6m_band_edge, chip->new_phy_layout);
+               chip->patch_cr157, chip->patch_6m_band_edge,
+               chip->new_phy_layout,
+               chip->link_led == LED1 ? 1 : 2,
+               chip->supports_tx_led);
        return 0;
 error:
        *rf_type = 0;
@@ -1181,7 +1184,7 @@ static int update_pwr_int(struct zd_chip *chip, u8 channel)
        u8 value = chip->pwr_int_values[channel - 1];
        dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_int %#04x\n",
                 channel, value);
-       return zd_iowrite32_locked(chip, value, CR31);
+       return zd_iowrite16_locked(chip, value, CR31);
 }
 
 static int update_pwr_cal(struct zd_chip *chip, u8 channel)
@@ -1189,12 +1192,12 @@ static int update_pwr_cal(struct zd_chip *chip, u8 channel)
        u8 value = chip->pwr_cal_values[channel-1];
        dev_dbg_f(zd_chip_dev(chip), "channel %d pwr_cal %#04x\n",
                 channel, value);
-       return zd_iowrite32_locked(chip, value, CR68);
+       return zd_iowrite16_locked(chip, value, CR68);
 }
 
 static int update_ofdm_cal(struct zd_chip *chip, u8 channel)
 {
-       struct zd_ioreq32 ioreqs[3];
+       struct zd_ioreq16 ioreqs[3];
 
        ioreqs[0].addr = CR67;
        ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1];
@@ -1206,7 +1209,7 @@ static int update_ofdm_cal(struct zd_chip *chip, u8 channel)
        dev_dbg_f(zd_chip_dev(chip),
                "channel %d ofdm_cal 36M %#04x 48M %#04x 54M %#04x\n",
                channel, ioreqs[0].value, ioreqs[1].value, ioreqs[2].value);
-       return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+       return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
 }
 
 static int update_channel_integration_and_calibration(struct zd_chip *chip,
@@ -1218,7 +1221,7 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
        if (r)
                return r;
        if (chip->is_zd1211b) {
-               static const struct zd_ioreq32 ioreqs[] = {
+               static const struct zd_ioreq16 ioreqs[] = {
                        { CR69, 0x28 },
                        {},
                        { CR69, 0x2a },
@@ -1230,7 +1233,7 @@ static int update_channel_integration_and_calibration(struct zd_chip *chip,
                r = update_pwr_cal(chip, channel);
                if (r)
                        return r;
-               r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+               r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
                if (r)
                        return r;
        }
@@ -1252,7 +1255,7 @@ static int patch_cck_gain(struct zd_chip *chip)
        if (r)
                return r;
        dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff);
-       return zd_iowrite32_locked(chip, value & 0xff, CR47);
+       return zd_iowrite16_locked(chip, value & 0xff, CR47);
 }
 
 int zd_chip_set_channel(struct zd_chip *chip, u8 channel)
@@ -1295,89 +1298,60 @@ u8 zd_chip_get_channel(struct zd_chip *chip)
        return channel;
 }
 
-static u16 led_mask(int led)
+int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
 {
-       switch (led) {
-       case 1:
-               return LED1;
-       case 2:
-               return LED2;
-       default:
-               return 0;
-       }
-}
-
-static int read_led_reg(struct zd_chip *chip, u16 *status)
-{
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       return zd_ioread16_locked(chip, status, CR_LED);
-}
-
-static int write_led_reg(struct zd_chip *chip, u16 status)
-{
-       ZD_ASSERT(mutex_is_locked(&chip->mutex));
-       return zd_iowrite16_locked(chip, status, CR_LED);
-}
+       static const zd_addr_t a[] = {
+               FW_LINK_STATUS,
+               CR_LED,
+       };
 
-int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status)
-{
-       int r, ret;
-       u16 mask = led_mask(led);
-       u16 reg;
+       int r;
+       u16 v[ARRAY_SIZE(a)];
+       struct zd_ioreq16 ioreqs[ARRAY_SIZE(a)] = {
+               [0] = { FW_LINK_STATUS },
+               [1] = { CR_LED },
+       };
+       u16 other_led;
 
-       if (!mask)
-               return -EINVAL;
        mutex_lock(&chip->mutex);
-       r = read_led_reg(chip, &reg);
+       r = zd_ioread16v_locked(chip, v, (const zd_addr_t *)a, ARRAY_SIZE(a));
        if (r)
-               return r;
+               goto out;
+
+       other_led = chip->link_led == LED1 ? LED2 : LED1;
+
        switch (status) {
-       case LED_STATUS:
-               return (reg & mask) ? LED_ON : LED_OFF;
        case LED_OFF:
-               reg &= ~mask;
-               ret = LED_OFF;
+               ioreqs[0].value = FW_LINK_OFF;
+               ioreqs[1].value = v[1] & ~(LED1|LED2);
                break;
-       case LED_FLIP:
-               reg ^= mask;
-               ret = (reg&mask) ? LED_ON : LED_OFF;
+       case LED_SCANNING:
+               ioreqs[0].value = FW_LINK_OFF;
+               ioreqs[1].value = v[1] & ~other_led;
+               if (get_seconds() % 3 == 0) {
+                       ioreqs[1].value &= ~chip->link_led;
+               } else {
+                       ioreqs[1].value |= chip->link_led;
+               }
                break;
-       case LED_ON:
-               reg |= mask;
-               ret = LED_ON;
+       case LED_ASSOCIATED:
+               ioreqs[0].value = FW_LINK_TX;
+               ioreqs[1].value = v[1] & ~other_led;
+               ioreqs[1].value |= chip->link_led;
                break;
        default:
-               return -EINVAL;
-       }
-       r = write_led_reg(chip, reg);
-       if (r) {
-               ret = r;
+               r = -EINVAL;
                goto out;
        }
-out:
-       mutex_unlock(&chip->mutex);
-       return r;
-}
-
-int zd_chip_led_flip(struct zd_chip *chip, int led,
-       const unsigned int *phases_msecs, unsigned int count)
-{
-       int i, r;
-       enum led_status status;
 
-       r = zd_chip_led_status(chip, led, LED_STATUS);
-       if (r)
-               return r;
-       status = r;
-       for (i = 0; i < count; i++) {
-               r = zd_chip_led_status(chip, led, LED_FLIP);
-               if (r < 0)
+       if (v[0] != ioreqs[0].value || v[1] != ioreqs[1].value) {
+               r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs));
+               if (r)
                        goto out;
-               msleep(phases_msecs[i]);
        }
-
+       r = 0;
 out:
-       zd_chip_led_status(chip, led, status);
+       mutex_unlock(&chip->mutex);
        return r;
 }
 
@@ -1679,4 +1653,3 @@ int zd_rfwritev_cr_locked(struct zd_chip *chip,
 
        return 0;
 }
-
index 4b12508598972a65040a44987e43531912a71003..ae59597ce4e16e5035e7910d4fc858501b347a2d 100644 (file)
 /* masks for controlling LEDs */
 #define LED1                           0x0100
 #define LED2                           0x0200
+#define LED_SW                         0x0400
 
 /* Seems to indicate that the configuration is over.
  */
 #define FW_SOFT_RESET           FW_REG(4)
 #define FW_FLASH_CHK            FW_REG(5)
 
+#define FW_LINK_OFF            0x0
+#define FW_LINK_TX             0x1
+/* 0x2 - link led on? */
+
 enum {
        CR_BASE_OFFSET                  = 0x9000,
        FW_START_OFFSET                 = 0xee00,
@@ -663,8 +668,11 @@ struct zd_chip {
        u8 pwr_int_values[E2P_CHANNEL_COUNT];
        /* SetPointOFDM in the vendor driver */
        u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT];
-       u8 pa_type:4, patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
-          new_phy_layout:1, is_zd1211b:1;
+       u16 link_led;
+       unsigned int pa_type:4,
+               patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1,
+               new_phy_layout:1,
+               is_zd1211b:1, supports_tx_led:1;
 };
 
 static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb)
@@ -812,15 +820,12 @@ int zd_chip_lock_phy_regs(struct zd_chip *chip);
 int zd_chip_unlock_phy_regs(struct zd_chip *chip);
 
 enum led_status {
-       LED_OFF    = 0,
-       LED_ON     = 1,
-       LED_FLIP   = 2,
-       LED_STATUS = 3,
+       LED_OFF = 0,
+       LED_SCANNING = 1,
+       LED_ASSOCIATED = 2,
 };
 
-int zd_chip_led_status(struct zd_chip *chip, int led, enum led_status status);
-int zd_chip_led_flip(struct zd_chip *chip, int led,
-                    const unsigned int *phases_msecs, unsigned int count);
+int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
 
 int zd_set_beacon_interval(struct zd_chip *chip, u32 interval);
 
index 1989f1c05fbee7bea30fa93888cf611e8c4b76a6..2d12837052b03f35f49e1f4ae21aa99c831653f7 100644 (file)
 static void ieee_init(struct ieee80211_device *ieee);
 static void softmac_init(struct ieee80211softmac_device *sm);
 
+static void housekeeping_init(struct zd_mac *mac);
+static void housekeeping_enable(struct zd_mac *mac);
+static void housekeeping_disable(struct zd_mac *mac);
+
 int zd_mac_init(struct zd_mac *mac,
                struct net_device *netdev,
                struct usb_interface *intf)
@@ -46,6 +50,7 @@ int zd_mac_init(struct zd_mac *mac,
        ieee_init(ieee);
        softmac_init(ieee80211_priv(netdev));
        zd_chip_init(&mac->chip, netdev, intf);
+       housekeeping_init(mac);
        return 0;
 }
 
@@ -178,6 +183,7 @@ int zd_mac_open(struct net_device *netdev)
        if (r < 0)
                goto disable_rx;
 
+       housekeeping_enable(mac);
        ieee80211softmac_start(netdev);
        return 0;
 disable_rx:
@@ -204,6 +210,7 @@ int zd_mac_stop(struct net_device *netdev)
         */
 
        zd_chip_disable_rx(chip);
+       housekeeping_disable(mac);
        ieee80211softmac_stop(netdev);
 
        zd_chip_disable_hwint(chip);
@@ -1080,3 +1087,46 @@ void zd_dump_rx_status(const struct rx_status *status)
        }
 }
 #endif /* DEBUG */
+
+#define LINK_LED_WORK_DELAY HZ
+
+static void link_led_handler(void *p)
+{
+       struct zd_mac *mac = p;
+       struct zd_chip *chip = &mac->chip;
+       struct ieee80211softmac_device *sm = ieee80211_priv(mac->netdev);
+       int is_associated;
+       int r;
+
+       spin_lock_irq(&mac->lock);
+       is_associated = sm->associated != 0;
+       spin_unlock_irq(&mac->lock);
+
+       r = zd_chip_control_leds(chip,
+                                is_associated ? LED_ASSOCIATED : LED_SCANNING);
+       if (r)
+               dev_err(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
+
+       queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
+                          LINK_LED_WORK_DELAY);
+}
+
+static void housekeeping_init(struct zd_mac *mac)
+{
+       INIT_WORK(&mac->housekeeping.link_led_work, link_led_handler, mac);
+}
+
+static void housekeeping_enable(struct zd_mac *mac)
+{
+       dev_dbg_f(zd_mac_dev(mac), "\n");
+       queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
+                          0);
+}
+
+static void housekeeping_disable(struct zd_mac *mac)
+{
+       dev_dbg_f(zd_mac_dev(mac), "\n");
+       cancel_rearming_delayed_workqueue(zd_workqueue,
+               &mac->housekeeping.link_led_work);
+       zd_chip_control_leds(&mac->chip, LED_OFF);
+}
index 29b51fd7d4e58f484e4eeb1520b9c8526cdc2f0d..b8ea3de7924afb95a8032b32853616f15f7f6867 100644 (file)
@@ -120,6 +120,10 @@ enum mac_flags {
        MAC_FIXED_CHANNEL = 0x01,
 };
 
+struct housekeeping {
+       struct work_struct link_led_work;
+};
+
 #define ZD_MAC_STATS_BUFFER_SIZE 16
 
 struct zd_mac {
@@ -128,6 +132,7 @@ struct zd_mac {
        struct net_device *netdev;
        /* Unlocked reading possible */
        struct iw_statistics iw_stats;
+       struct housekeeping housekeeping;
        unsigned int stats_count;
        u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
        u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE];
index 440ef24b5fd10a445c525093bf799a65c6d348c4..af3a7b36d078c03e96dadbbe08ee6e744ff6d6b1 100644 (file)
@@ -82,7 +82,7 @@ static int iw_get_nick(struct net_device *netdev,
                       union iwreq_data *req, char *extra)
 {
        strcpy(extra, "zd1211");
-       req->data.length = strlen(extra) + 1;
+       req->data.length = strlen(extra);
        req->data.flags = 1;
        return 0;
 }
index 31027e52b04b1f17b27f17c1272a0c1c7ee105ba..5c265ad0485af0c08a46e706dfc6b16b25f6b562 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/errno.h>
 #include <linux/skbuff.h>
 #include <linux/usb.h>
+#include <linux/workqueue.h>
 #include <net/ieee80211.h>
 
 #include "zd_def.h"
@@ -1112,12 +1113,20 @@ static struct usb_driver driver = {
        .disconnect     = disconnect,
 };
 
+struct workqueue_struct *zd_workqueue;
+
 static int __init usb_init(void)
 {
        int r;
 
        pr_debug("usb_init()\n");
 
+       zd_workqueue = create_singlethread_workqueue(driver.name);
+       if (zd_workqueue == NULL) {
+               printk(KERN_ERR "%s: couldn't create workqueue\n", driver.name);
+               return -ENOMEM;
+       }
+
        r = usb_register(&driver);
        if (r) {
                printk(KERN_ERR "usb_register() failed. Error number %d\n", r);
@@ -1132,6 +1141,7 @@ static void __exit usb_exit(void)
 {
        pr_debug("usb_exit()\n");
        usb_deregister(&driver);
+       destroy_workqueue(zd_workqueue);
 }
 
 module_init(usb_init);
index ded39de5f72de55d0815d68ccdf8328c90f19e4f..e81a2d3cfffd2ad4dd166f0084031565aac9f524 100644 (file)
@@ -238,4 +238,6 @@ int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
 
 int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits);
 
+extern struct workqueue_struct *zd_workqueue;
+
 #endif /* _ZD_USB_H */
index 71c2da277d6e6a398b13b8041195a41f540f409d..5756401fb15bb2e13d272ef87f4ce6f3752ab8cd 100644 (file)
@@ -31,7 +31,6 @@ static struct inode * oprofilefs_get_inode(struct super_block * sb, int mode)
                inode->i_mode = mode;
                inode->i_uid = 0;
                inode->i_gid = 0;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        }
@@ -110,8 +109,8 @@ static ssize_t ulong_write_file(struct file * file, char const __user * buf, siz
 
 static int default_open(struct inode * inode, struct file * filp)
 {
-       if (inode->u.generic_ip)
-               filp->private_data = inode->u.generic_ip;
+       if (inode->i_private)
+               filp->private_data = inode->i_private;
        return 0;
 }
 
@@ -158,7 +157,7 @@ int oprofilefs_create_ulong(struct super_block * sb, struct dentry * root,
        if (!d)
                return -EFAULT;
 
-       d->d_inode->u.generic_ip = val;
+       d->d_inode->i_private = val;
        return 0;
 }
 
@@ -171,7 +170,7 @@ int oprofilefs_create_ro_ulong(struct super_block * sb, struct dentry * root,
        if (!d)
                return -EFAULT;
 
-       d->d_inode->u.generic_ip = val;
+       d->d_inode->i_private = val;
        return 0;
 }
 
@@ -197,7 +196,7 @@ int oprofilefs_create_ro_atomic(struct super_block * sb, struct dentry * root,
        if (!d)
                return -EFAULT;
 
-       d->d_inode->u.generic_ip = val;
+       d->d_inode->i_private = val;
        return 0;
 }
 
index 4d762fc4878cc0d328121185cf80c356a7f4f6b6..c27e782e6df999de618dc5a96e6cfd2ec15f6939 100644 (file)
@@ -17,6 +17,31 @@ config PCI_MSI
 
           If you don't know what to do here, say N.
 
+config PCI_MULTITHREAD_PROBE
+       bool "PCI Multi-threaded probe (EXPERIMENTAL)"
+       depends on PCI && EXPERIMENTAL
+       help
+         Say Y here if you want the PCI core to spawn a new thread for
+         every PCI device that is probed.  This can cause a huge
+         speedup in boot times on multiprocessor machines, and even a
+         smaller speedup on single processor machines.
+
+         But it can also cause lots of bad things to happen.  A number
+         of PCI drivers can not properly handle running in this way,
+         some will just not work properly at all, while others might
+         decide to blow up power supplies with a huge load all at once,
+         so use this option at your own risk.
+
+         It is very unwise to use this option if you are not using a
+         boot process that can handle devices being created in any
+         order.  A program that can create persistant block and network
+         device names (like udev) is a good idea if you wish to use
+         this option.
+
+         Again, use this option at your own risk, you have been warned!
+
+         When in doubt, say N.
+
 config PCI_DEBUG
        bool "PCI Debugging"
        depends on PCI && DEBUG_KERNEL
index 5f7db9d2436e76141e15d50a44e9f1fc38e54378..aadaa3c8096b73ecf50428b044b0151c6f10b50d 100644 (file)
@@ -77,9 +77,12 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
  * This adds a single pci device to the global
  * device list and adds sysfs and procfs entries
  */
-void __devinit pci_bus_add_device(struct pci_dev *dev)
+int __devinit pci_bus_add_device(struct pci_dev *dev)
 {
-       device_add(&dev->dev);
+       int retval;
+       retval = device_add(&dev->dev);
+       if (retval)
+               return retval;
 
        down_write(&pci_bus_sem);
        list_add_tail(&dev->global_list, &pci_devices);
@@ -87,6 +90,7 @@ void __devinit pci_bus_add_device(struct pci_dev *dev)
 
        pci_proc_attach_device(dev);
        pci_create_sysfs_dev_files(dev);
+       return 0;
 }
 
 /**
@@ -104,6 +108,7 @@ void __devinit pci_bus_add_device(struct pci_dev *dev)
 void __devinit pci_bus_add_devices(struct pci_bus *bus)
 {
        struct pci_dev *dev;
+       int retval;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                /*
@@ -112,7 +117,9 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
                 */
                if (!list_empty(&dev->global_list))
                        continue;
-               pci_bus_add_device(dev);
+               retval = pci_bus_add_device(dev);
+               if (retval)
+                       dev_err(&dev->dev, "Error adding device, continuing\n");
        }
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -129,10 +136,13 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
                               list_add_tail(&dev->subordinate->node,
                                               &dev->bus->children);
                               up_write(&pci_bus_sem);
-                      }
+                       }
                        pci_bus_add_devices(dev->subordinate);
-
-                       sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge");
+                       retval = sysfs_create_link(&dev->subordinate->class_dev.kobj,
+                                                  &dev->dev.kobj, "bridge");
+                       if (retval)
+                               dev_err(&dev->dev, "Error creating sysfs "
+                                       "bridge symlink, continuing...\n");
                }
        }
 }
index be104eced34c63ffea077e1e8d64f93cad1e56e5..7fff07e877c71982b89b672eea06b7617d89e13e 100644 (file)
@@ -150,6 +150,11 @@ struct acpiphp_attention_info
        struct module *owner;
 };
 
+struct acpiphp_ioapic {
+       struct pci_dev *dev;
+       u32 gsi_base;
+       struct list_head list;
+};
 
 /* PCI bus bridge HID */
 #define ACPI_PCI_HOST_HID              "PNP0A03"
index ae67a8f55ba169851ad7c78bf1cdd83c7c67f047..83e8e4412de5834fff05c3558cf911d94146f48f 100644 (file)
@@ -53,6 +53,8 @@
 #include "acpiphp.h"
 
 static LIST_HEAD(bridge_list);
+static LIST_HEAD(ioapic_list);
+static DEFINE_SPINLOCK(ioapic_list_lock);
 
 #define MY_NAME "acpiphp_glue"
 
@@ -797,6 +799,7 @@ ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
        struct pci_dev *pdev;
        u32 gsi_base;
        u64 phys_addr;
+       struct acpiphp_ioapic *ioapic;
 
        /* Evaluate _STA if present */
        status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
@@ -811,41 +814,107 @@ ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
        if (get_gsi_base(handle, &gsi_base))
                return AE_OK;
 
+       ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL);
+       if (!ioapic)
+               return AE_NO_MEMORY;
+
        pdev = get_apic_pci_info(handle);
        if (!pdev)
-               return AE_OK;
+               goto exit_kfree;
 
-       if (pci_enable_device(pdev)) {
-               pci_dev_put(pdev);
-               return AE_OK;
-       }
+       if (pci_enable_device(pdev))
+               goto exit_pci_dev_put;
 
        pci_set_master(pdev);
 
-       if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) {
-               pci_disable_device(pdev);
-               pci_dev_put(pdev);
-               return AE_OK;
-       }
+       if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)"))
+               goto exit_pci_disable_device;
 
        phys_addr = pci_resource_start(pdev, 0);
-       if (acpi_register_ioapic(handle, phys_addr, gsi_base)) {
-               pci_release_region(pdev, 0);
-               pci_disable_device(pdev);
-               pci_dev_put(pdev);
+       if (acpi_register_ioapic(handle, phys_addr, gsi_base))
+               goto exit_pci_release_region;
+
+       ioapic->gsi_base = gsi_base;
+       ioapic->dev = pdev;
+       spin_lock(&ioapic_list_lock);
+       list_add_tail(&ioapic->list, &ioapic_list);
+       spin_unlock(&ioapic_list_lock);
+
+       return AE_OK;
+
+ exit_pci_release_region:
+       pci_release_region(pdev, 0);
+ exit_pci_disable_device:
+       pci_disable_device(pdev);
+ exit_pci_dev_put:
+       pci_dev_put(pdev);
+ exit_kfree:
+       kfree(ioapic);
+
+       return AE_OK;
+}
+
+static acpi_status
+ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+       acpi_status status;
+       unsigned long sta;
+       acpi_handle tmp;
+       u32 gsi_base;
+       struct acpiphp_ioapic *pos, *n, *ioapic = NULL;
+
+       /* Evaluate _STA if present */
+       status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
+       if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
+               return AE_CTRL_DEPTH;
+
+       /* Scan only PCI bus scope */
+       status = acpi_get_handle(handle, "_HID", &tmp);
+       if (ACPI_SUCCESS(status))
+               return AE_CTRL_DEPTH;
+
+       if (get_gsi_base(handle, &gsi_base))
                return AE_OK;
+
+       acpi_unregister_ioapic(handle, gsi_base);
+
+       spin_lock(&ioapic_list_lock);
+       list_for_each_entry_safe(pos, n, &ioapic_list, list) {
+               if (pos->gsi_base != gsi_base)
+                       continue;
+               ioapic = pos;
+               list_del(&ioapic->list);
+               break;
        }
+       spin_unlock(&ioapic_list_lock);
+
+       if (!ioapic)
+               return AE_OK;
+
+       pci_release_region(ioapic->dev, 0);
+       pci_disable_device(ioapic->dev);
+       pci_dev_put(ioapic->dev);
+       kfree(ioapic);
 
        return AE_OK;
 }
 
 static int acpiphp_configure_ioapics(acpi_handle handle)
 {
+       ioapic_add(handle, 0, NULL, NULL);
        acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
                            ACPI_UINT32_MAX, ioapic_add, NULL, NULL);
        return 0;
 }
 
+static int acpiphp_unconfigure_ioapics(acpi_handle handle)
+{
+       ioapic_remove(handle, 0, NULL, NULL);
+       acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+                           ACPI_UINT32_MAX, ioapic_remove, NULL, NULL);
+       return 0;
+}
+
 static int power_on_slot(struct acpiphp_slot *slot)
 {
        acpi_status status;
@@ -997,7 +1066,7 @@ acpiphp_bus_add_out:
  * @handle: handle to acpi namespace
  *
  */
-int acpiphp_bus_trim(acpi_handle handle)
+static int acpiphp_bus_trim(acpi_handle handle)
 {
        struct acpi_device *device;
        int retval;
@@ -1074,10 +1143,11 @@ static int enable_device(struct acpiphp_slot *slot)
 
        pci_bus_assign_resources(bus);
        acpiphp_sanitize_bus(bus);
+       acpiphp_set_hpp_values(slot->bridge->handle, bus);
+       list_for_each_entry(func, &slot->funcs, sibling)
+               acpiphp_configure_ioapics(func->handle);
        pci_enable_bridges(bus);
        pci_bus_add_devices(bus);
-       acpiphp_set_hpp_values(slot->bridge->handle, bus);
-       acpiphp_configure_ioapics(slot->bridge->handle);
 
        /* associate pci_dev to our representation */
        list_for_each (l, &slot->funcs) {
@@ -1103,6 +1173,16 @@ static int enable_device(struct acpiphp_slot *slot)
        return retval;
 }
 
+static void disable_bridges(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               if (dev->subordinate) {
+                       disable_bridges(dev->subordinate);
+                       pci_disable_device(dev);
+               }
+       }
+}
 
 /**
  * disable_device - disable a slot
@@ -1127,6 +1207,19 @@ static int disable_device(struct acpiphp_slot *slot)
                        func->bridge = NULL;
                }
 
+               if (func->pci_dev) {
+                       pci_stop_bus_device(func->pci_dev);
+                       if (func->pci_dev->subordinate) {
+                               disable_bridges(func->pci_dev->subordinate);
+                               pci_disable_device(func->pci_dev);
+                       }
+               }
+       }
+
+       list_for_each (l, &slot->funcs) {
+               func = list_entry(l, struct acpiphp_func, sibling);
+
+               acpiphp_unconfigure_ioapics(func->handle);
                acpiphp_bus_trim(func->handle);
                /* try to remove anyway.
                 * acpiphp_bus_add might have been failed */
index 317457dd401451b2797f8c8135165d983f09d5f1..d0a07d9ab30c8e314dad00a2eab0becbf118d788 100644 (file)
@@ -487,9 +487,7 @@ static void __exit ibm_acpiphp_exit(void)
        if (ACPI_FAILURE(status))
                err("%s: Notification handler removal failed\n", __FUNCTION__);
        /* remove the /sys entries */
-       if (sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr))
-               err("%s: removal of sysfs file apci_table failed\n",
-                               __FUNCTION__);
+       sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr);
 }
 
 module_init(ibm_acpiphp_init);
index 8b3da007e859abc803a9109ba046ba31e6be432c..5bab666cd67e138015657f23ef837bea332c5a6e 100644 (file)
@@ -140,7 +140,7 @@ struct ctrl_dbg {
 
 static int open(struct inode *inode, struct file *file)
 {
-       struct controller *ctrl = inode->u.generic_ip;
+       struct controller *ctrl = inode->i_private;
        struct ctrl_dbg *dbg;
        int retval = -ENOMEM;
 
index dd2b762777c4bbb72a8086401173c6e9e2707ce8..05a4f0f9018620b5f6999c701d8a73ffbb477659 100644 (file)
@@ -176,7 +176,9 @@ static void pci_rescan_slot(struct pci_dev *temp)
        struct pci_bus *bus = temp->bus;
        struct pci_dev *dev;
        int func;
+       int retval;
        u8 hdr_type;
+
        if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) {
                temp->hdr_type = hdr_type & 0x7f;
                if (!pci_find_slot(bus->number, temp->devfn)) {
@@ -185,8 +187,12 @@ static void pci_rescan_slot(struct pci_dev *temp)
                                dbg("New device on %s function %x:%x\n",
                                        bus->name, temp->devfn >> 3,
                                        temp->devfn & 7);
-                               pci_bus_add_device(dev);
-                               add_slot(dev);
+                               retval = pci_bus_add_device(dev);
+                               if (retval)
+                                       dev_err(&dev->dev, "error adding "
+                                               "device, continuing.\n");
+                               else
+                                       add_slot(dev);
                        }
                }
                /* multifunction device? */
@@ -205,8 +211,12 @@ static void pci_rescan_slot(struct pci_dev *temp)
                                        dbg("New device on %s function %x:%x\n",
                                                bus->name, temp->devfn >> 3,
                                                temp->devfn & 7);
-                                       pci_bus_add_device(dev);
-                                       add_slot(dev);
+                                       retval = pci_bus_add_device(dev);
+                                       if (retval)
+                                               dev_err(&dev->dev, "error adding "
+                                                       "device, continuing.\n");
+                                       else
+                                               add_slot(dev);
                                }
                        }
                }
index e929b7c114296c6a348af75fe921731a0f2e8220..772523dc3860f57e5bc8b2f5d4e8d89c82044c0e 100644 (file)
@@ -172,8 +172,8 @@ struct hotplug_slot {
 
 extern int pci_hp_register             (struct hotplug_slot *slot);
 extern int pci_hp_deregister           (struct hotplug_slot *slot);
-extern int pci_hp_change_slot_info     (struct hotplug_slot *slot,
-                                        struct hotplug_slot_info *info);
+extern int __must_check pci_hp_change_slot_info        (struct hotplug_slot *slot,
+                                                struct hotplug_slot_info *info);
 extern struct subsystem pci_hotplug_slots_subsys;
 
 /* PCI Setting Record (Type 0) */
index b7b378df89e3ffeb2a3fda1debb70558a02b401d..e2823ea9c4ed829ffda3298da97ac3574dc40312 100644 (file)
@@ -482,31 +482,95 @@ static int has_test_file (struct hotplug_slot *slot)
 
 static int fs_add_slot (struct hotplug_slot *slot)
 {
-       if (has_power_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+       int retval = 0;
 
-       if (has_attention_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+       if (has_power_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+               if (retval)
+                       goto exit_power;
+       }
 
-       if (has_latch_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+       if (has_attention_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_attention.attr);
+               if (retval)
+                       goto exit_attention;
+       }
 
-       if (has_adapter_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+       if (has_latch_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_latch.attr);
+               if (retval)
+                       goto exit_latch;
+       }
 
-       if (has_address_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_address.attr);
+       if (has_adapter_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_presence.attr);
+               if (retval)
+                       goto exit_adapter;
+       }
 
-       if (has_max_bus_speed_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
+       if (has_address_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_address.attr);
+               if (retval)
+                       goto exit_address;
+       }
 
+       if (has_max_bus_speed_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_max_bus_speed.attr);
+               if (retval)
+                       goto exit_max_speed;
+       }
+
+       if (has_cur_bus_speed_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_cur_bus_speed.attr);
+               if (retval)
+                       goto exit_cur_speed;
+       }
+
+       if (has_test_file(slot) == 0) {
+               retval = sysfs_create_file(&slot->kobj,
+                                          &hotplug_slot_attr_test.attr);
+               if (retval)
+                       goto exit_test;
+       }
+
+       goto exit;
+
+exit_test:
        if (has_cur_bus_speed_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
 
-       if (has_test_file(slot) == 0)
-               sysfs_create_file(&slot->kobj, &hotplug_slot_attr_test.attr);
+exit_cur_speed:
+       if (has_max_bus_speed_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
 
-       return 0;
+exit_max_speed:
+       if (has_address_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_address.attr);
+
+exit_address:
+       if (has_adapter_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+
+exit_adapter:
+       if (has_latch_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+
+exit_latch:
+       if (has_attention_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+
+exit_attention:
+       if (has_power_file(slot) == 0)
+               sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+exit_power:
+exit:
+       return retval;
 }
 
 static void fs_remove_slot (struct hotplug_slot *slot)
@@ -626,8 +690,11 @@ int pci_hp_deregister (struct hotplug_slot *slot)
  *
  * Returns 0 if successful, anything else for an error.
  */
-int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info *info)
+int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
+                                        struct hotplug_slot_info *info)
 {
+       int retval;
+
        if ((slot == NULL) || (info == NULL))
                return -ENODEV;
 
@@ -636,32 +703,60 @@ int pci_hp_change_slot_info (struct hotplug_slot *slot, struct hotplug_slot_info
        * for the files referring to the fields that have now changed.
        */
        if ((has_power_file(slot) == 0) &&
-           (slot->info->power_status != info->power_status))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_power.attr);
+           (slot->info->power_status != info->power_status)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_power.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_attention_file(slot) == 0) &&
-           (slot->info->attention_status != info->attention_status))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_attention.attr);
+           (slot->info->attention_status != info->attention_status)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_attention.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_latch_file(slot) == 0) &&
-           (slot->info->latch_status != info->latch_status))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_latch.attr);
+           (slot->info->latch_status != info->latch_status)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_latch.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_adapter_file(slot) == 0) &&
-           (slot->info->adapter_status != info->adapter_status))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_presence.attr);
+           (slot->info->adapter_status != info->adapter_status)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_presence.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_address_file(slot) == 0) &&
-           (slot->info->address != info->address))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_address.attr);
+           (slot->info->address != info->address)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_address.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_max_bus_speed_file(slot) == 0) &&
-           (slot->info->max_bus_speed != info->max_bus_speed))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_max_bus_speed.attr);
+           (slot->info->max_bus_speed != info->max_bus_speed)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_max_bus_speed.attr);
+               if (retval)
+                       return retval;
+       }
 
        if ((has_cur_bus_speed_file(slot) == 0) &&
-           (slot->info->cur_bus_speed != info->cur_bus_speed))
-               sysfs_update_file(&slot->kobj, &hotplug_slot_attr_cur_bus_speed.attr);
+           (slot->info->cur_bus_speed != info->cur_bus_speed)) {
+               retval = sysfs_update_file(&slot->kobj,
+                                          &hotplug_slot_attr_cur_bus_speed.attr);
+               if (retval)
+                       return retval;
+       }
 
        memcpy (slot->info, info, sizeof (struct hotplug_slot_info));
 
index 33d19876835626a6be7e4aa226aa459c3a5c9860..41290a106bd8c4661fd1f1204c213a5db64c32ef 100644 (file)
@@ -762,14 +762,14 @@ int pciehp_enable_slot(struct slot *p_slot)
        if (rc || !getstatus) {
                info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
                mutex_unlock(&p_slot->ctrl->crit_sect);
-               return 1;
+               return -ENODEV;
        }
        if (MRL_SENS(p_slot->ctrl->ctrlcap)) {  
                rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
                if (rc || getstatus) {
                        info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
-                       return 1;
+                       return -ENODEV;
                }
        }
        
@@ -778,7 +778,7 @@ int pciehp_enable_slot(struct slot *p_slot)
                if (rc || getstatus) {
                        info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
-                       return 1;
+                       return -EINVAL;
                }
        }
        mutex_unlock(&p_slot->ctrl->crit_sect);
@@ -813,7 +813,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                if (ret || !getstatus) {
                        info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
-                       return 1;
+                       return -ENODEV;
                }
        }
 
@@ -822,7 +822,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                if (ret || getstatus) {
                        info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
-                       return 1;
+                       return -ENODEV;
                }
        }
 
@@ -831,7 +831,7 @@ int pciehp_disable_slot(struct slot *p_slot)
                if (ret || !getstatus) {
                        info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
                        mutex_unlock(&p_slot->ctrl->crit_sect);
-                       return 1;
+                       return -EINVAL;
                }
        }
 
index 8ad446605f756fe3afad4feaea3d9e7c82cd0a1a..2b9e10e38613327bee8c6767609c2522892d12f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * PCI Hot Plug Controller Skeleton Driver - 0.2
+ * PCI Hot Plug Controller Skeleton Driver - 0.3
  *
  * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (C) 2001,2003 IBM Corp.
@@ -21,7 +21,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * This driver is to be used as a skeleton driver to be show how to interface
+ * This driver is to be used as a skeleton driver to show how to interface
  * with the pci hotplug core easily.
  *
  * Send feedback to <greg@kroah.com>
@@ -58,8 +58,6 @@ static LIST_HEAD(slot_list);
 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
 
-
-
 /* local variables */
 static int debug;
 static int num_slots;
@@ -109,7 +107,6 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
        return retval;
 }
 
-
 static int disable_slot(struct hotplug_slot *hotplug_slot)
 {
        struct slot *slot = hotplug_slot->private;
@@ -342,7 +339,7 @@ static int __init pcihp_skel_init(void)
        info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
        /*
         * Do specific initialization stuff for your driver here
-        * Like initializing your controller hardware (if any) and
+        * like initializing your controller hardware (if any) and
         * determining the number of slots you have in the system
         * right now.
         */
index 7208b95c6ee779585ff056bcdaeb091140f44961..c7103ac5cd06b76da2c0ec60381003601bd98bc1 100644 (file)
@@ -173,7 +173,7 @@ struct controller {
 #define msg_button_cancel      "PCI slot #%s - action canceled due to button press.\n"
 
 /* sysfs functions for the hotplug controller info */
-extern void shpchp_create_ctrl_files   (struct controller *ctrl);
+extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl);
 
 extern int     shpchp_sysfs_enable_slot(struct slot *slot);
 extern int     shpchp_sysfs_disable_slot(struct slot *slot);
index a14e7de1984621cd9281751df06cc0624fee5d87..235c18a22393d04e0ba86ec5f511d086149f6d75 100644 (file)
@@ -449,10 +449,14 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                ctrl->speed = PCI_SPEED_33MHz;
        }
 
-       shpchp_create_ctrl_files(ctrl);
+       rc = shpchp_create_ctrl_files(ctrl);
+       if (rc)
+               goto err_cleanup_slots;
 
        return 0;
 
+err_cleanup_slots:
+       cleanup_slots(ctrl);
 err_out_release_ctlr:
        ctrl->hpc_ops->release_ctlr(ctrl);
 err_out_free_ctrl:
index 620e1139e607c763dfaa69ff25413c971de82310..29fa9d26adae28b0e49e0a39e16796439f1c4b4f 100644 (file)
@@ -91,9 +91,9 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
 }
 static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
 
-void shpchp_create_ctrl_files (struct controller *ctrl)
+int __must_check shpchp_create_ctrl_files (struct controller *ctrl)
 {
-       device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
+       return device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl);
 }
 
 void shpchp_remove_ctrl_files(struct controller *ctrl)
index a83c1f5735d69bc05418e5963dbbcbc975a06a11..27a057409eca1d53d37ca41d3d2fa4a6844de868 100644 (file)
@@ -45,16 +45,10 @@ msi_register(struct msi_ops *ops)
        return 0;
 }
 
-static void msi_cache_ctor(void *p, kmem_cache_t *cache, unsigned long flags)
-{
-       memset(p, 0, sizeof(struct msi_desc));
-}
-
 static int msi_cache_init(void)
 {
-       msi_cachep = kmem_cache_create("msi_cache",
-                       sizeof(struct msi_desc),
-                       0, SLAB_HWCACHE_ALIGN, msi_cache_ctor, NULL);
+       msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc),
+                                       0, SLAB_HWCACHE_ALIGN, NULL, NULL);
        if (!msi_cachep)
                return -ENOMEM;
 
@@ -402,11 +396,10 @@ static struct msi_desc* alloc_msi_entry(void)
 {
        struct msi_desc *entry;
 
-       entry = kmem_cache_alloc(msi_cachep, SLAB_KERNEL);
+       entry = kmem_cache_zalloc(msi_cachep, GFP_KERNEL);
        if (!entry)
                return NULL;
 
-       memset(entry, 0, sizeof(struct msi_desc));
        entry->link.tail = entry->link.head = 0;        /* single message */
        entry->dev = NULL;
 
@@ -900,6 +893,33 @@ static int msix_capability_init(struct pci_dev *dev,
        return 0;
 }
 
+/**
+ * pci_msi_supported - check whether MSI may be enabled on device
+ * @dev: pointer to the pci_dev data structure of MSI device function
+ *
+ * MSI must be globally enabled and supported by the device and its root
+ * bus. But, the root bus is not easy to find since some architectures
+ * have virtual busses on top of the PCI hierarchy (for instance the
+ * hypertransport bus), while the actual bus where MSI must be supported
+ * is below. So we test the MSI flag on all parent busses and assume
+ * that no quirk will ever set the NO_MSI flag on a non-root bus.
+ **/
+static
+int pci_msi_supported(struct pci_dev * dev)
+{
+       struct pci_bus *bus;
+
+       if (!pci_msi_enable || !dev || dev->no_msi)
+               return -EINVAL;
+
+       /* check MSI flags of all parent busses */
+       for (bus = dev->bus; bus; bus = bus->parent)
+               if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
+                       return -EINVAL;
+
+       return 0;
+}
+
 /**
  * pci_enable_msi - configure device's MSI capability structure
  * @dev: pointer to the pci_dev data structure of MSI device function
@@ -912,19 +932,11 @@ static int msix_capability_init(struct pci_dev *dev,
  **/
 int pci_enable_msi(struct pci_dev* dev)
 {
-       struct pci_bus *bus;
-       int pos, temp, status = -EINVAL;
+       int pos, temp, status;
        u16 control;
 
-       if (!pci_msi_enable || !dev)
-               return status;
-
-       if (dev->no_msi)
-               return status;
-
-       for (bus = dev->bus; bus; bus = bus->parent)
-               if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
-                       return -EINVAL;
+       if (pci_msi_supported(dev) < 0)
+               return -EINVAL;
 
        temp = dev->irq;
 
@@ -1134,22 +1146,14 @@ static int reroute_msix_table(int head, struct msix_entry *entries, int *nvec)
  **/
 int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec)
 {
-       struct pci_bus *bus;
        int status, pos, nr_entries, free_vectors;
        int i, j, temp;
        u16 control;
        unsigned long flags;
 
-       if (!pci_msi_enable || !dev || !entries)
+       if (!entries || pci_msi_supported(dev) < 0)
                return -EINVAL;
 
-       if (dev->no_msi)
-               return -EINVAL;
-
-       for (bus = dev->bus; bus; bus = bus->parent)
-               if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI)
-                       return -EINVAL;
-
        status = msi_init();
        if (status < 0)
                return status;
index 474e9cd0e9e474ce81bb70ca4d54b2a01566adcc..b1c0c707d96ccc6e713042b1d67167609199c723 100644 (file)
  *  Registration of PCI drivers and handling of hot-pluggable devices.
  */
 
+/* multithreaded probe logic */
+static int pci_multithread_probe =
+#ifdef CONFIG_PCI_MULTITHREAD_PROBE
+       1;
+#else
+       0;
+#endif
+__module_param_call("", pci_multithread_probe, param_set_bool, param_get_bool, &pci_multithread_probe, 0644);
+
+
 /*
  * Dynamic device IDs are disabled for !CONFIG_HOTPLUG
  */
@@ -46,6 +56,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
                subdevice=PCI_ANY_ID, class=0, class_mask=0;
        unsigned long driver_data=0;
        int fields=0;
+       int retval = 0;
 
        fields = sscanf(buf, "%x %x %x %x %x %x %lux",
                        &vendor, &device, &subvendor, &subdevice,
@@ -72,10 +83,12 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
        spin_unlock(&pdrv->dynids.lock);
 
        if (get_driver(&pdrv->driver)) {
-               driver_attach(&pdrv->driver);
+               retval = driver_attach(&pdrv->driver);
                put_driver(&pdrv->driver);
        }
 
+       if (retval)
+               return retval;
        return count;
 }
 static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
@@ -279,6 +292,18 @@ static int pci_device_suspend(struct device * dev, pm_message_t state)
        return i;
 }
 
+static int pci_device_suspend_late(struct device * dev, pm_message_t state)
+{
+       struct pci_dev * pci_dev = to_pci_dev(dev);
+       struct pci_driver * drv = pci_dev->driver;
+       int i = 0;
+
+       if (drv && drv->suspend_late) {
+               i = drv->suspend_late(pci_dev, state);
+               suspend_report_result(drv->suspend_late, i);
+       }
+       return i;
+}
 
 /*
  * Default resume method for devices that have no driver provided resume,
@@ -313,6 +338,17 @@ static int pci_device_resume(struct device * dev)
        return error;
 }
 
+static int pci_device_resume_early(struct device * dev)
+{
+       int error = 0;
+       struct pci_dev * pci_dev = to_pci_dev(dev);
+       struct pci_driver * drv = pci_dev->driver;
+
+       if (drv && drv->resume_early)
+               error = drv->resume_early(pci_dev);
+       return error;
+}
+
 static void pci_device_shutdown(struct device *dev)
 {
        struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -386,6 +422,11 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner)
        drv->driver.owner = owner;
        drv->driver.kobj.ktype = &pci_driver_kobj_type;
 
+       if (pci_multithread_probe)
+               drv->driver.multithread_probe = pci_multithread_probe;
+       else
+               drv->driver.multithread_probe = drv->multithread_probe;
+
        spin_lock_init(&drv->dynids.lock);
        INIT_LIST_HEAD(&drv->dynids.list);
 
@@ -509,8 +550,10 @@ struct bus_type pci_bus_type = {
        .probe          = pci_device_probe,
        .remove         = pci_device_remove,
        .suspend        = pci_device_suspend,
-       .shutdown       = pci_device_shutdown,
+       .suspend_late   = pci_device_suspend_late,
+       .resume_early   = pci_device_resume_early,
        .resume         = pci_device_resume,
+       .shutdown       = pci_device_shutdown,
        .dev_attrs      = pci_dev_attrs,
 };
 
index fdefa7dcd15675758f31c3ce3ababd69368433d4..a1d2e979b17fdd1e431297b78c88fbf926da99ac 100644 (file)
@@ -117,6 +117,7 @@ is_enabled_store(struct device *dev, struct device_attribute *attr,
                const char *buf, size_t count)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
+       int retval = 0;
 
        /* this can crash the machine when done on the "wrong" device */
        if (!capable(CAP_SYS_ADMIN))
@@ -126,11 +127,53 @@ is_enabled_store(struct device *dev, struct device_attribute *attr,
                pci_disable_device(pdev);
 
        if (*buf == '1')
-               pci_enable_device(pdev);
+               retval = pci_enable_device(pdev);
 
+       if (retval)
+               return retval;
        return count;
 }
 
+static ssize_t
+msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       if (!pdev->subordinate)
+               return 0;
+
+       return sprintf (buf, "%u\n",
+                       !(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI));
+}
+
+static ssize_t
+msi_bus_store(struct device *dev, struct device_attribute *attr,
+             const char *buf, size_t count)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       /* bad things may happen if the no_msi flag is changed
+        * while some drivers are loaded */
+       if (!capable(CAP_SYS_ADMIN))
+               return count;
+
+       if (!pdev->subordinate)
+               return count;
+
+       if (*buf == '0') {
+               pdev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
+               dev_warn(&pdev->dev, "forced subordinate bus to not support MSI,"
+                        " bad things could happen.\n");
+       }
+
+       if (*buf == '1') {
+               pdev->subordinate->bus_flags &= ~PCI_BUS_FLAGS_NO_MSI;
+               dev_warn(&pdev->dev, "forced subordinate bus to support MSI,"
+                        " bad things could happen.\n");
+       }
+
+       return count;
+}
 
 struct device_attribute pci_dev_attrs[] = {
        __ATTR_RO(resource),
@@ -145,6 +188,7 @@ struct device_attribute pci_dev_attrs[] = {
        __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),
+       __ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store),
        __ATTR_NULL,
 };
 
@@ -384,16 +428,39 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
        return pci_mmap_page_range(pdev, vma, mmap_type, 0);
 }
 
+/**
+ * pci_remove_resource_files - cleanup resource files
+ * @dev: dev to cleanup
+ *
+ * If we created resource files for @dev, remove them from sysfs and
+ * free their resources.
+ */
+static void
+pci_remove_resource_files(struct pci_dev *pdev)
+{
+       int i;
+
+       for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+               struct bin_attribute *res_attr;
+
+               res_attr = pdev->res_attr[i];
+               if (res_attr) {
+                       sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
+                       kfree(res_attr);
+               }
+       }
+}
+
 /**
  * pci_create_resource_files - create resource files in sysfs for @dev
  * @dev: dev in question
  *
  * Walk the resources in @dev creating files for each resource available.
  */
-static void
-pci_create_resource_files(struct pci_dev *pdev)
+static int pci_create_resource_files(struct pci_dev *pdev)
 {
        int i;
+       int retval;
 
        /* Expose the PCI resources from this device as files */
        for (i = 0; i < PCI_ROM_RESOURCE; i++) {
@@ -416,35 +483,19 @@ pci_create_resource_files(struct pci_dev *pdev)
                        res_attr->size = pci_resource_len(pdev, i);
                        res_attr->mmap = pci_mmap_resource;
                        res_attr->private = &pdev->resource[i];
-                       sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
-               }
-       }
-}
-
-/**
- * pci_remove_resource_files - cleanup resource files
- * @dev: dev to cleanup
- *
- * If we created resource files for @dev, remove them from sysfs and
- * free their resources.
- */
-static void
-pci_remove_resource_files(struct pci_dev *pdev)
-{
-       int i;
-
-       for (i = 0; i < PCI_ROM_RESOURCE; i++) {
-               struct bin_attribute *res_attr;
-
-               res_attr = pdev->res_attr[i];
-               if (res_attr) {
-                       sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
-                       kfree(res_attr);
+                       retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
+                       if (retval) {
+                               pci_remove_resource_files(pdev);
+                               return retval;
+                       }
+               } else {
+                       return -ENOMEM;
                }
        }
+       return 0;
 }
 #else /* !HAVE_PCI_MMAP */
-static inline void pci_create_resource_files(struct pci_dev *dev) { return; }
+static inline int pci_create_resource_files(struct pci_dev *dev) { return 0; }
 static inline void pci_remove_resource_files(struct pci_dev *dev) { return; }
 #endif /* HAVE_PCI_MMAP */
 
@@ -529,22 +580,27 @@ static struct bin_attribute pcie_config_attr = {
        .write = pci_write_config,
 };
 
-int pci_create_sysfs_dev_files (struct pci_dev *pdev)
+int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
 {
+       struct bin_attribute *rom_attr = NULL;
+       int retval;
+
        if (!sysfs_initialized)
                return -EACCES;
 
        if (pdev->cfg_size < 4096)
-               sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
+               retval = sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
        else
-               sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+               retval = sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+       if (retval)
+               goto err;
 
-       pci_create_resource_files(pdev);
+       retval = pci_create_resource_files(pdev);
+       if (retval)
+               goto err_bin_file;
 
        /* If the device has a ROM, try to expose it in sysfs. */
        if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
-               struct bin_attribute *rom_attr;
-               
                rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC);
                if (rom_attr) {
                        pdev->rom_attr = rom_attr;
@@ -554,13 +610,28 @@ int pci_create_sysfs_dev_files (struct pci_dev *pdev)
                        rom_attr->attr.owner = THIS_MODULE;
                        rom_attr->read = pci_read_rom;
                        rom_attr->write = pci_write_rom;
-                       sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
+                       retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
+                       if (retval)
+                               goto err_rom;
+               } else {
+                       retval = -ENOMEM;
+                       goto err_bin_file;
                }
        }
        /* add platform-specific attributes */
        pcibios_add_platform_entries(pdev);
-       
+
        return 0;
+
+err_rom:
+       kfree(rom_attr);
+err_bin_file:
+       if (pdev->cfg_size < 4096)
+               sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
+       else
+               sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+err:
+       return retval;
 }
 
 /**
@@ -589,10 +660,14 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
 static int __init pci_sysfs_init(void)
 {
        struct pci_dev *pdev = NULL;
-       
+       int retval;
+
        sysfs_initialized = 1;
-       for_each_pci_dev(pdev)
-               pci_create_sysfs_dev_files(pdev);
+       for_each_pci_dev(pdev) {
+               retval = pci_create_sysfs_dev_files(pdev);
+               if (retval)
+                       return retval;
+       }
 
        return 0;
 }
index 9f79dd6d51ab7b8b0fbe18ab77f20fd0630e81ee..a544997399b307a7efa50b7854dd7b6e63340487 100644 (file)
@@ -432,10 +432,12 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
        case PM_EVENT_ON:
                return PCI_D0;
        case PM_EVENT_FREEZE:
+       case PM_EVENT_PRETHAW:
+               /* REVISIT both freeze and pre-thaw "should" use D0 */
        case PM_EVENT_SUSPEND:
                return PCI_D3hot;
        default:
-               printk("They asked me for state %d\n", state.event);
+               printk("Unrecognized suspend event %d\n", state.event);
                BUG();
        }
        return PCI_D0;
@@ -443,6 +445,51 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)
 
 EXPORT_SYMBOL(pci_choose_state);
 
+static int pci_save_pcie_state(struct pci_dev *dev)
+{
+       int pos, i = 0;
+       struct pci_cap_saved_state *save_state;
+       u16 *cap;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (pos <= 0)
+               return 0;
+
+       save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+       if (!save_state) {
+               dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
+               return -ENOMEM;
+       }
+       cap = (u16 *)&save_state->data[0];
+
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &cap[i++]);
+       pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
+       pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
+       pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
+       pci_add_saved_cap(dev, save_state);
+       return 0;
+}
+
+static void pci_restore_pcie_state(struct pci_dev *dev)
+{
+       int i = 0, pos;
+       struct pci_cap_saved_state *save_state;
+       u16 *cap;
+
+       save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!save_state || pos <= 0)
+               return;
+       cap = (u16 *)&save_state->data[0];
+
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, cap[i++]);
+       pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, cap[i++]);
+       pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
+       pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
+       pci_remove_saved_cap(save_state);
+       kfree(save_state);
+}
+
 /**
  * pci_save_state - save the PCI configuration space of a device before suspending
  * @dev: - PCI device that we're dealing with
@@ -458,6 +505,8 @@ pci_save_state(struct pci_dev *dev)
                return i;
        if ((i = pci_save_msix_state(dev)) != 0)
                return i;
+       if ((i = pci_save_pcie_state(dev)) != 0)
+               return i;
        return 0;
 }
 
@@ -471,6 +520,9 @@ pci_restore_state(struct pci_dev *dev)
        int i;
        int val;
 
+       /* PCI Express register must be restored first */
+       pci_restore_pcie_state(dev);
+
        /*
         * The Base Address register should be programmed before the command
         * register(s)
@@ -953,13 +1005,12 @@ static int __devinit pci_setup(char *str)
                }
                str = k;
        }
-       return 1;
+       return 0;
 }
+early_param("pci", pci_setup);
 
 device_initcall(pci_init);
 
-__setup("pci=", pci_setup);
-
 #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
 /* FIXME: Some boxes have multiple ISA bridges! */
 struct pci_dev *isa_bridge;
index 08d58fc78ee1cafc522702fd26618e4b43d66a4f..6bf327db5c5e70fd39d62f060ca8d5cbd95da1de 100644 (file)
@@ -42,7 +42,7 @@ extern void pci_remove_legacy_files(struct pci_bus *bus);
 /* Lock for read/write access to pci device and bus lists */
 extern struct rw_semaphore pci_bus_sem;
 
-#ifdef CONFIG_X86_IO_APIC
+#ifdef CONFIG_PCI_MSI
 extern int pci_msi_quirk;
 #else
 #define pci_msi_quirk 0
index 1012db8b8b2c4b6d093d93bc2e65053fba3e71d3..0ad92a8ad8b1a831007dc58cd47554a7be0ac68a 100644 (file)
@@ -34,3 +34,4 @@ config HOTPLUG_PCI_PCIE_POLL_EVENT_MODE
           
          When in doubt, say N.
 
+source "drivers/pci/pcie/aer/Kconfig"
index 984fa87283e3a3f7e0b3228cf36d53a8147d56dd..e00fb99acf44434934d05db3dc33959eeebd5650 100644 (file)
@@ -5,3 +5,6 @@
 pcieportdrv-y                  := portdrv_core.o portdrv_pci.o portdrv_bus.o
 
 obj-$(CONFIG_PCIEPORTBUS)      += pcieportdrv.o
+
+# Build PCI Express AER if needed
+obj-$(CONFIG_PCIEAER)          += aer/
diff --git a/drivers/pci/pcie/aer/Kconfig b/drivers/pci/pcie/aer/Kconfig
new file mode 100644 (file)
index 0000000..3f37a60
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# PCI Express Root Port Device AER Configuration
+#
+
+config PCIEAER
+       boolean "Root Port Advanced Error Reporting support"
+       depends on PCIEPORTBUS && ACPI
+       default y
+       help
+         This enables PCI Express Root Port Advanced Error Reporting
+         (AER) driver support. Error reporting messages sent to Root
+         Port will be handled by PCI Express AER driver.
diff --git a/drivers/pci/pcie/aer/Makefile b/drivers/pci/pcie/aer/Makefile
new file mode 100644 (file)
index 0000000..15a4f40
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Makefile for PCI-Express Root Port Advanced Error Reporting Driver
+#
+
+obj-$(CONFIG_PCIEAER) += aerdriver.o
+
+aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o aerdrv_acpi.o
+
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
new file mode 100644 (file)
index 0000000..0d4ac02
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * drivers/pci/pcie/aer/aerdrv.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * This file implements the AER root port service driver. The driver will
+ * register an irq handler. When root port triggers an AER interrupt, the irq
+ * handler will collect root port status and schedule a work.
+ *
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/pcieport_if.h>
+
+#include "aerdrv.h"
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0"
+#define DRIVER_AUTHOR "tom.l.nguyen@intel.com"
+#define DRIVER_DESC "Root Port Advanced Error Reporting Driver"
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+static int __devinit aer_probe (struct pcie_device *dev,
+       const struct pcie_port_service_id *id );
+static void aer_remove(struct pcie_device *dev);
+static int aer_suspend(struct pcie_device *dev, pm_message_t state)
+{return 0;}
+static int aer_resume(struct pcie_device *dev) {return 0;}
+static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
+       enum pci_channel_state error);
+static void aer_error_resume(struct pci_dev *dev);
+static pci_ers_result_t aer_root_reset(struct pci_dev *dev);
+
+/*
+ * PCI Express bus's AER Root service driver data structure
+ */
+static struct pcie_port_service_id aer_id[] = {
+       {
+       .vendor         = PCI_ANY_ID,
+       .device         = PCI_ANY_ID,
+       .port_type      = PCIE_RC_PORT,
+       .service_type   = PCIE_PORT_SERVICE_AER,
+       },
+       { /* end: all zeroes */ }
+};
+
+static struct pci_error_handlers aer_error_handlers = {
+       .error_detected = aer_error_detected,
+       .resume = aer_error_resume,
+};
+
+static struct pcie_port_service_driver aerdrv = {
+       .name           = "aer",
+       .id_table       = &aer_id[0],
+
+       .probe          = aer_probe,
+       .remove         = aer_remove,
+
+       .suspend        = aer_suspend,
+       .resume         = aer_resume,
+
+       .err_handler    = &aer_error_handlers,
+
+       .reset_link     = aer_root_reset,
+};
+
+/**
+ * aer_irq - Root Port's ISR
+ * @irq: IRQ assigned to Root Port
+ * @context: pointer to Root Port data structure
+ * @r: pointer struct pt_regs
+ *
+ * Invoked when Root Port detects AER messages.
+ **/
+static irqreturn_t aer_irq(int irq, void *context, struct pt_regs * r)
+{
+       unsigned int status, id;
+       struct pcie_device *pdev = (struct pcie_device *)context;
+       struct aer_rpc *rpc = get_service_data(pdev);
+       int next_prod_idx;
+       unsigned long flags;
+       int pos;
+
+       pos = pci_find_aer_capability(pdev->port);
+       /*
+        * Must lock access to Root Error Status Reg, Root Error ID Reg,
+        * and Root error producer/consumer index
+        */
+       spin_lock_irqsave(&rpc->e_lock, flags);
+
+       /* Read error status */
+       pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
+       if (!(status & ROOT_ERR_STATUS_MASKS)) {
+               spin_unlock_irqrestore(&rpc->e_lock, flags);
+               return IRQ_NONE;
+       }
+
+       /* Read error source and clear error status */
+       pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_COR_SRC, &id);
+       pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
+
+       /* Store error source for later DPC handler */
+       next_prod_idx = rpc->prod_idx + 1;
+       if (next_prod_idx == AER_ERROR_SOURCES_MAX)
+               next_prod_idx = 0;
+       if (next_prod_idx == rpc->cons_idx) {
+               /*
+                * Error Storm Condition - possibly the same error occurred.
+                * Drop the error.
+                */
+               spin_unlock_irqrestore(&rpc->e_lock, flags);
+               return IRQ_HANDLED;
+       }
+       rpc->e_sources[rpc->prod_idx].status =  status;
+       rpc->e_sources[rpc->prod_idx].id = id;
+       rpc->prod_idx = next_prod_idx;
+       spin_unlock_irqrestore(&rpc->e_lock, flags);
+
+       /*  Invoke DPC handler */
+       schedule_work(&rpc->dpc_handler);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * aer_alloc_rpc - allocate Root Port data structure
+ * @dev: pointer to the pcie_dev data structure
+ *
+ * Invoked when Root Port's AER service is loaded.
+ **/
+static struct aer_rpc* aer_alloc_rpc(struct pcie_device *dev)
+{
+       struct aer_rpc *rpc;
+
+       if (!(rpc = (struct aer_rpc *)kmalloc(sizeof(struct aer_rpc),
+               GFP_KERNEL)))
+               return NULL;
+
+       memset(rpc, 0, sizeof(struct aer_rpc));
+       /*
+        * Initialize Root lock access, e_lock, to Root Error Status Reg,
+        * Root Error ID Reg, and Root error producer/consumer index.
+        */
+       rpc->e_lock = SPIN_LOCK_UNLOCKED;
+
+       rpc->rpd = dev;
+       INIT_WORK(&rpc->dpc_handler, aer_isr, (void *)dev);
+       rpc->prod_idx = rpc->cons_idx = 0;
+       mutex_init(&rpc->rpc_mutex);
+       init_waitqueue_head(&rpc->wait_release);
+
+       /* Use PCIE bus function to store rpc into PCIE device */
+       set_service_data(dev, rpc);
+
+       return rpc;
+}
+
+/**
+ * aer_remove - clean up resources
+ * @dev: pointer to the pcie_dev data structure
+ *
+ * Invoked when PCI Express bus unloads or AER probe fails.
+ **/
+static void aer_remove(struct pcie_device *dev)
+{
+       struct aer_rpc *rpc = get_service_data(dev);
+
+       if (rpc) {
+               /* If register interrupt service, it must be free. */
+               if (rpc->isr)
+                       free_irq(dev->irq, dev);
+
+               wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
+
+               aer_delete_rootport(rpc);
+               set_service_data(dev, NULL);
+       }
+}
+
+/**
+ * aer_probe - initialize resources
+ * @dev: pointer to the pcie_dev data structure
+ * @id: pointer to the service id data structure
+ *
+ * Invoked when PCI Express bus loads AER service driver.
+ **/
+static int __devinit aer_probe (struct pcie_device *dev,
+                               const struct pcie_port_service_id *id )
+{
+       int status;
+       struct aer_rpc *rpc;
+       struct device *device = &dev->device;
+
+       /* Init */
+       if ((status = aer_init(dev)))
+               return status;
+
+       /* Alloc rpc data structure */
+       if (!(rpc = aer_alloc_rpc(dev))) {
+               printk(KERN_DEBUG "%s: Alloc rpc fails on PCIE device[%s]\n",
+                       __FUNCTION__, device->bus_id);
+               aer_remove(dev);
+               return -ENOMEM;
+       }
+
+       /* Request IRQ ISR */
+       if ((status = request_irq(dev->irq, aer_irq, SA_SHIRQ, "aerdrv",
+                               dev))) {
+               printk(KERN_DEBUG "%s: Request ISR fails on PCIE device[%s]\n",
+                       __FUNCTION__, device->bus_id);
+               aer_remove(dev);
+               return status;
+       }
+
+       rpc->isr = 1;
+
+       aer_enable_rootport(rpc);
+
+       return status;
+}
+
+/**
+ * aer_root_reset - reset link on Root Port
+ * @dev: pointer to Root Port's pci_dev data structure
+ *
+ * Invoked by Port Bus driver when performing link reset at Root Port.
+ **/
+static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
+{
+       u16 p2p_ctrl;
+       u32 status;
+       int pos;
+
+       pos = pci_find_aer_capability(dev);
+
+       /* Disable Root's interrupt in response to error messages */
+       pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, 0);
+
+       /* Assert Secondary Bus Reset */
+       pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &p2p_ctrl);
+       p2p_ctrl |= PCI_CB_BRIDGE_CTL_CB_RESET;
+       pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
+
+       /* De-assert Secondary Bus Reset */
+       p2p_ctrl &= ~PCI_CB_BRIDGE_CTL_CB_RESET;
+       pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
+
+       /*
+        * System software must wait for at least 100ms from the end
+        * of a reset of one or more device before it is permitted
+        * to issue Configuration Requests to those devices.
+        */
+       msleep(200);
+       printk(KERN_DEBUG "Complete link reset at Root[%s]\n", dev->dev.bus_id);
+
+       /* Enable Root Port's interrupt in response to error messages */
+       pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status);
+       pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status);
+       pci_write_config_dword(dev,
+               pos + PCI_ERR_ROOT_COMMAND,
+               ROOT_PORT_INTR_ON_MESG_MASK);
+
+       return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * aer_error_detected - update severity status
+ * @dev: pointer to Root Port's pci_dev data structure
+ * @error: error severity being notified by port bus
+ *
+ * Invoked by Port Bus driver during error recovery.
+ **/
+static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
+                       enum pci_channel_state error)
+{
+       /* Root Port has no impact. Always recovers. */
+       return PCI_ERS_RESULT_CAN_RECOVER;
+}
+
+/**
+ * aer_error_resume - clean up corresponding error status bits
+ * @dev: pointer to Root Port's pci_dev data structure
+ *
+ * Invoked by Port Bus driver during nonfatal recovery.
+ **/
+static void aer_error_resume(struct pci_dev *dev)
+{
+       int pos;
+       u32 status, mask;
+       u16 reg16;
+
+       /* Clean up Root device status */
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
+       pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16);
+
+       /* Clean AER Root Error Status */
+       pos = pci_find_aer_capability(dev);
+       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
+       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
+       if (dev->error_state == pci_channel_io_normal)
+               status &= ~mask; /* Clear corresponding nonfatal bits */
+       else
+               status &= mask; /* Clear corresponding fatal bits */
+       pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+}
+
+/**
+ * aer_service_init - register AER root service driver
+ *
+ * Invoked when AER root service driver is loaded.
+ **/
+static int __init aer_service_init(void)
+{
+       return pcie_port_service_register(&aerdrv);
+}
+
+/**
+ * aer_service_exit - unregister AER root service driver
+ *
+ * Invoked when AER root service driver is unloaded.
+ **/
+static void __exit aer_service_exit(void)
+{
+       pcie_port_service_unregister(&aerdrv);
+}
+
+module_init(aer_service_init);
+module_exit(aer_service_exit);
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
new file mode 100644 (file)
index 0000000..daf0cad
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ */
+
+#ifndef _AERDRV_H_
+#define _AERDRV_H_
+
+#include <linux/pcieport_if.h>
+#include <linux/aer.h>
+
+#define AER_NONFATAL                   0
+#define AER_FATAL                      1
+#define AER_CORRECTABLE                        2
+#define AER_UNCORRECTABLE              4
+#define AER_ERROR_MASK                 0x001fffff
+#define AER_ERROR(d)                   (d & AER_ERROR_MASK)
+
+#define OSC_METHOD_RUN_SUCCESS         0
+#define OSC_METHOD_NOT_SUPPORTED       1
+#define OSC_METHOD_RUN_FAILURE         2
+
+/* Root Error Status Register Bits */
+#define ROOT_ERR_STATUS_MASKS                  0x0f
+
+#define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE|   \
+                                       PCI_EXP_RTCTL_SENFEE|   \
+                                       PCI_EXP_RTCTL_SEFEE)
+#define ROOT_PORT_INTR_ON_MESG_MASK    (PCI_ERR_ROOT_CMD_COR_EN|       \
+                                       PCI_ERR_ROOT_CMD_NONFATAL_EN|   \
+                                       PCI_ERR_ROOT_CMD_FATAL_EN)
+#define ERR_COR_ID(d)                  (d & 0xffff)
+#define ERR_UNCOR_ID(d)                        (d >> 16)
+
+#define AER_SUCCESS                    0
+#define AER_UNSUCCESS                  1
+#define AER_ERROR_SOURCES_MAX          100
+
+#define AER_LOG_TLP_MASKS              (PCI_ERR_UNC_POISON_TLP|        \
+                                       PCI_ERR_UNC_ECRC|               \
+                                       PCI_ERR_UNC_UNSUP|              \
+                                       PCI_ERR_UNC_COMP_ABORT|         \
+                                       PCI_ERR_UNC_UNX_COMP|           \
+                                       PCI_ERR_UNC_MALF_TLP)
+
+/* AER Error Info Flags */
+#define AER_TLP_HEADER_VALID_FLAG      0x00000001
+#define AER_MULTI_ERROR_VALID_FLAG     0x00000002
+
+#define ERR_CORRECTABLE_ERROR_MASK     0x000031c1
+#define ERR_UNCORRECTABLE_ERROR_MASK   0x001ff010
+
+struct header_log_regs {
+       unsigned int dw0;
+       unsigned int dw1;
+       unsigned int dw2;
+       unsigned int dw3;
+};
+
+struct aer_err_info {
+       int severity;                   /* 0:NONFATAL | 1:FATAL | 2:COR */
+       int flags;
+       unsigned int status;            /* COR/UNCOR Error Status */
+       struct header_log_regs tlp;     /* TLP Header */
+};
+
+struct aer_err_source {
+       unsigned int status;
+       unsigned int id;
+};
+
+struct aer_rpc {
+       struct pcie_device *rpd;        /* Root Port device */
+       struct work_struct dpc_handler;
+       struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX];
+       unsigned short prod_idx;        /* Error Producer Index */
+       unsigned short cons_idx;        /* Error Consumer Index */
+       int isr;
+       spinlock_t e_lock;              /*
+                                        * Lock access to Error Status/ID Regs
+                                        * and error producer/consumer index
+                                        */
+       struct mutex rpc_mutex;         /*
+                                        * only one thread could do
+                                        * recovery on the same
+                                        * root port hierachy
+                                        */
+       wait_queue_head_t wait_release;
+};
+
+struct aer_broadcast_data {
+       enum pci_channel_state state;
+       enum pci_ers_result result;
+};
+
+static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
+               enum pci_ers_result new)
+{
+       switch (orig) {
+       case PCI_ERS_RESULT_CAN_RECOVER:
+       case PCI_ERS_RESULT_RECOVERED:
+               orig = new;
+               break;
+       case PCI_ERS_RESULT_DISCONNECT:
+               if (new == PCI_ERS_RESULT_NEED_RESET)
+                       orig = new;
+               break;
+       default:
+               break;
+       }
+
+       return orig;
+}
+
+extern struct bus_type pcie_port_bus_type;
+extern void aer_enable_rootport(struct aer_rpc *rpc);
+extern void aer_delete_rootport(struct aer_rpc *rpc);
+extern int aer_init(struct pcie_device *dev);
+extern void aer_isr(void *context);
+extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
+extern int aer_osc_setup(struct pci_dev *dev);
+
+#endif //_AERDRV_H_
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
new file mode 100644 (file)
index 0000000..fa68e89
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Access ACPI _OSC method
+ *
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/acpi.h>
+#include <linux/pci-acpi.h>
+#include <linux/delay.h>
+#include "aerdrv.h"
+
+/**
+ * aer_osc_setup - run ACPI _OSC method
+ *
+ * Return:
+ *     Zero if success. Nonzero for otherwise.
+ *
+ * Invoked when PCIE bus loads AER service driver. To avoid conflict with
+ * BIOS AER support requires BIOS to yield AER control to OS native driver.
+ **/
+int aer_osc_setup(struct pci_dev *dev)
+{
+       int retval = OSC_METHOD_RUN_SUCCESS;
+       acpi_status status;
+       acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
+       struct pci_dev *pdev = dev;
+       struct pci_bus *parent;
+
+       while (!handle) {
+               if (!pdev || !pdev->bus->parent)
+                       break;
+               parent = pdev->bus->parent;
+               if (!parent->self)
+                       /* Parent must be a host bridge */
+                       handle = acpi_get_pci_rootbridge_handle(
+                                       pci_domain_nr(parent),
+                                       parent->number);
+               else
+                       handle = DEVICE_ACPI_HANDLE(
+                                       &(parent->self->dev));
+               pdev = parent->self;
+       }
+
+       if (!handle)
+               return OSC_METHOD_NOT_SUPPORTED;
+
+       pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
+       status = pci_osc_control_set(handle, OSC_PCI_EXPRESS_AER_CONTROL |
+               OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
+       if (ACPI_FAILURE(status)) {
+               if (status == AE_SUPPORT)
+                       retval = OSC_METHOD_NOT_SUPPORTED;
+               else
+                       retval = OSC_METHOD_RUN_FAILURE;
+       }
+
+       return retval;
+}
+
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
new file mode 100644 (file)
index 0000000..1c7e660
--- /dev/null
@@ -0,0 +1,758 @@
+/*
+ * drivers/pci/pcie/aer/aerdrv_core.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * This file implements the core part of PCI-Express AER. When an pci-express
+ * error is delivered, an error message will be collected and printed to
+ * console, then, an error recovery procedure will be executed by following
+ * the pci error recovery rules.
+ *
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/suspend.h>
+#include <linux/acpi.h>
+#include <linux/pci-acpi.h>
+#include <linux/delay.h>
+#include "aerdrv.h"
+
+static int forceload;
+module_param(forceload, bool, 0);
+
+#define PCI_CFG_SPACE_SIZE     (0x100)
+int pci_find_aer_capability(struct pci_dev *dev)
+{
+       int pos;
+       u32 reg32 = 0;
+
+       /* Check if it's a pci-express device */
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!pos)
+               return 0;
+
+       /* Check if it supports pci-express AER */
+       pos = PCI_CFG_SPACE_SIZE;
+       while (pos) {
+               if (pci_read_config_dword(dev, pos, &reg32))
+                       return 0;
+
+               /* some broken boards return ~0 */
+               if (reg32 == 0xffffffff)
+                       return 0;
+
+               if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
+                       break;
+
+               pos = reg32 >> 20;
+       }
+
+       return pos;
+}
+
+int pci_enable_pcie_error_reporting(struct pci_dev *dev)
+{
+       u16 reg16 = 0;
+       int pos;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!pos)
+               return -EIO;
+
+       pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, &reg16);
+       reg16 = reg16 |
+               PCI_EXP_DEVCTL_CERE |
+               PCI_EXP_DEVCTL_NFERE |
+               PCI_EXP_DEVCTL_FERE |
+               PCI_EXP_DEVCTL_URRE;
+       pci_write_config_word(dev, pos+PCI_EXP_DEVCTL,
+                       reg16);
+       return 0;
+}
+
+int pci_disable_pcie_error_reporting(struct pci_dev *dev)
+{
+       u16 reg16 = 0;
+       int pos;
+
+       pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+       if (!pos)
+               return -EIO;
+
+       pci_read_config_word(dev, pos+PCI_EXP_DEVCTL, &reg16);
+       reg16 = reg16 & ~(PCI_EXP_DEVCTL_CERE |
+                       PCI_EXP_DEVCTL_NFERE |
+                       PCI_EXP_DEVCTL_FERE |
+                       PCI_EXP_DEVCTL_URRE);
+       pci_write_config_word(dev, pos+PCI_EXP_DEVCTL,
+                       reg16);
+       return 0;
+}
+
+int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
+{
+       int pos;
+       u32 status, mask;
+
+       pos = pci_find_aer_capability(dev);
+       if (!pos)
+               return -EIO;
+
+       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
+       pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
+       if (dev->error_state == pci_channel_io_normal)
+               status &= ~mask; /* Clear corresponding nonfatal bits */
+       else
+               status &= mask; /* Clear corresponding fatal bits */
+       pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+
+       return 0;
+}
+
+static int find_device_iter(struct device *device, void *data)
+{
+       struct pci_dev *dev;
+       u16 id = *(unsigned long *)data;
+       u8 secondary, subordinate, d_bus = id >> 8;
+
+       if (device->bus == &pci_bus_type) {
+               dev = to_pci_dev(device);
+               if (id == ((dev->bus->number << 8) | dev->devfn)) {
+                       /*
+                        * Device ID match
+                        */
+                       *(unsigned long*)data = (unsigned long)device;
+                       return 1;
+               }
+
+               /*
+                * If device is P2P, check if it is an upstream?
+                */
+               if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
+                       pci_read_config_byte(dev, PCI_SECONDARY_BUS,
+                               &secondary);
+                       pci_read_config_byte(dev, PCI_SUBORDINATE_BUS,
+                               &subordinate);
+                       if (d_bus >= secondary && d_bus <= subordinate) {
+                               *(unsigned long*)data = (unsigned long)device;
+                               return 1;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+/**
+ * find_source_device - search through device hierarchy for source device
+ * @p_dev: pointer to Root Port pci_dev data structure
+ * @id: device ID of agent who sends an error message to this Root Port
+ *
+ * Invoked when error is detected at the Root Port.
+ **/
+static struct device* find_source_device(struct pci_dev *parent, u16 id)
+{
+       struct pci_dev *dev = parent;
+       struct device *device;
+       unsigned long device_addr;
+       int status;
+
+       /* Is Root Port an agent that sends error message? */
+       if (id == ((dev->bus->number << 8) | dev->devfn))
+               return &dev->dev;
+
+       do {
+               device_addr = id;
+               if ((status = device_for_each_child(&dev->dev,
+                       &device_addr, find_device_iter))) {
+                       device = (struct device*)device_addr;
+                       dev = to_pci_dev(device);
+                       if (id == ((dev->bus->number << 8) | dev->devfn))
+                               return device;
+               }
+       }while (status);
+
+       return NULL;
+}
+
+static void report_error_detected(struct pci_dev *dev, void *data)
+{
+       pci_ers_result_t vote;
+       struct pci_error_handlers *err_handler;
+       struct aer_broadcast_data *result_data;
+       result_data = (struct aer_broadcast_data *) data;
+
+       dev->error_state = result_data->state;
+
+       if (!dev->driver ||
+               !dev->driver->err_handler ||
+               !dev->driver->err_handler->error_detected) {
+               if (result_data->state == pci_channel_io_frozen &&
+                       !(dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)) {
+                       /*
+                        * In case of fatal recovery, if one of down-
+                        * stream device has no driver. We might be
+                        * unable to recover because a later insmod
+                        * of a driver for this device is unaware of
+                        * its hw state.
+                        */
+                       printk(KERN_DEBUG "Device ID[%s] has %s\n",
+                                       dev->dev.bus_id, (dev->driver) ?
+                                       "no AER-aware driver" : "no driver");
+               }
+               return;
+       }
+
+       err_handler = dev->driver->err_handler;
+       vote = err_handler->error_detected(dev, result_data->state);
+       result_data->result = merge_result(result_data->result, vote);
+       return;
+}
+
+static void report_mmio_enabled(struct pci_dev *dev, void *data)
+{
+       pci_ers_result_t vote;
+       struct pci_error_handlers *err_handler;
+       struct aer_broadcast_data *result_data;
+       result_data = (struct aer_broadcast_data *) data;
+
+       if (!dev->driver ||
+               !dev->driver->err_handler ||
+               !dev->driver->err_handler->mmio_enabled)
+               return;
+
+       err_handler = dev->driver->err_handler;
+       vote = err_handler->mmio_enabled(dev);
+       result_data->result = merge_result(result_data->result, vote);
+       return;
+}
+
+static void report_slot_reset(struct pci_dev *dev, void *data)
+{
+       pci_ers_result_t vote;
+       struct pci_error_handlers *err_handler;
+       struct aer_broadcast_data *result_data;
+       result_data = (struct aer_broadcast_data *) data;
+
+       if (!dev->driver ||
+               !dev->driver->err_handler ||
+               !dev->driver->err_handler->slot_reset)
+               return;
+
+       err_handler = dev->driver->err_handler;
+       vote = err_handler->slot_reset(dev);
+       result_data->result = merge_result(result_data->result, vote);
+       return;
+}
+
+static void report_resume(struct pci_dev *dev, void *data)
+{
+       struct pci_error_handlers *err_handler;
+
+       dev->error_state = pci_channel_io_normal;
+
+       if (!dev->driver ||
+               !dev->driver->err_handler ||
+               !dev->driver->err_handler->slot_reset)
+               return;
+
+       err_handler = dev->driver->err_handler;
+       err_handler->resume(dev);
+       return;
+}
+
+/**
+ * broadcast_error_message - handle message broadcast to downstream drivers
+ * @device: pointer to from where in a hierarchy message is broadcasted down
+ * @api: callback to be broadcasted
+ * @state: error state
+ *
+ * Invoked during error recovery process. Once being invoked, the content
+ * of error severity will be broadcasted to all downstream drivers in a
+ * hierarchy in question.
+ **/
+static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
+       enum pci_channel_state state,
+       char *error_mesg,
+       void (*cb)(struct pci_dev *, void *))
+{
+       struct aer_broadcast_data result_data;
+
+       printk(KERN_DEBUG "Broadcast %s message\n", error_mesg);
+       result_data.state = state;
+       if (cb == report_error_detected)
+               result_data.result = PCI_ERS_RESULT_CAN_RECOVER;
+       else
+               result_data.result = PCI_ERS_RESULT_RECOVERED;
+
+       if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE) {
+               /*
+                * If the error is reported by a bridge, we think this error
+                * is related to the downstream link of the bridge, so we
+                * do error recovery on all subordinates of the bridge instead
+                * of the bridge and clear the error status of the bridge.
+                */
+               if (cb == report_error_detected)
+                       dev->error_state = state;
+               pci_walk_bus(dev->subordinate, cb, &result_data);
+               if (cb == report_resume) {
+                       pci_cleanup_aer_uncorrect_error_status(dev);
+                       dev->error_state = pci_channel_io_normal;
+               }
+       }
+       else {
+               /*
+                * If the error is reported by an end point, we think this
+                * error is related to the upstream link of the end point.
+                */
+               pci_walk_bus(dev->bus, cb, &result_data);
+       }
+
+       return result_data.result;
+}
+
+struct find_aer_service_data {
+       struct pcie_port_service_driver *aer_driver;
+       int is_downstream;
+};
+
+static int find_aer_service_iter(struct device *device, void *data)
+{
+       struct device_driver *driver;
+       struct pcie_port_service_driver *service_driver;
+       struct pcie_device *pcie_dev;
+       struct find_aer_service_data *result;
+
+       result = (struct find_aer_service_data *) data;
+
+       if (device->bus == &pcie_port_bus_type) {
+               pcie_dev = to_pcie_device(device);
+               if (pcie_dev->id.port_type == PCIE_SW_DOWNSTREAM_PORT)
+                       result->is_downstream = 1;
+
+               driver = device->driver;
+               if (driver) {
+                       service_driver = to_service_driver(driver);
+                       if (service_driver->id_table->service_type ==
+                                       PCIE_PORT_SERVICE_AER) {
+                               result->aer_driver = service_driver;
+                               return 1;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static void find_aer_service(struct pci_dev *dev,
+               struct find_aer_service_data *data)
+{
+       int retval;
+       retval = device_for_each_child(&dev->dev, data, find_aer_service_iter);
+}
+
+static pci_ers_result_t reset_link(struct pcie_device *aerdev,
+               struct pci_dev *dev)
+{
+       struct pci_dev *udev;
+       pci_ers_result_t status;
+       struct find_aer_service_data data;
+
+       if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE)
+               udev = dev;
+       else
+               udev= dev->bus->self;
+
+       data.is_downstream = 0;
+       data.aer_driver = NULL;
+       find_aer_service(udev, &data);
+
+       /*
+        * Use the aer driver of the error agent firstly.
+        * If it hasn't the aer driver, use the root port's
+        */
+       if (!data.aer_driver || !data.aer_driver->reset_link) {
+               if (data.is_downstream &&
+                       aerdev->device.driver &&
+                       to_service_driver(aerdev->device.driver)->reset_link) {
+                       data.aer_driver =
+                               to_service_driver(aerdev->device.driver);
+               } else {
+                       printk(KERN_DEBUG "No link-reset support to Device ID"
+                               "[%s]\n",
+                               dev->dev.bus_id);
+                       return PCI_ERS_RESULT_DISCONNECT;
+               }
+       }
+
+       status = data.aer_driver->reset_link(udev);
+       if (status != PCI_ERS_RESULT_RECOVERED) {
+               printk(KERN_DEBUG "Link reset at upstream Device ID"
+                       "[%s] failed\n",
+                       udev->dev.bus_id);
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+
+       return status;
+}
+
+/**
+ * do_recovery - handle nonfatal/fatal error recovery process
+ * @aerdev: pointer to a pcie_device data structure of root port
+ * @dev: pointer to a pci_dev data structure of agent detecting an error
+ * @severity: error severity type
+ *
+ * Invoked when an error is nonfatal/fatal. Once being invoked, broadcast
+ * error detected message to all downstream drivers within a hierarchy in
+ * question and return the returned code.
+ **/
+static pci_ers_result_t do_recovery(struct pcie_device *aerdev,
+               struct pci_dev *dev,
+               int severity)
+{
+       pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED;
+       enum pci_channel_state state;
+
+       if (severity == AER_FATAL)
+               state = pci_channel_io_frozen;
+       else
+               state = pci_channel_io_normal;
+
+       status = broadcast_error_message(dev,
+                       state,
+                       "error_detected",
+                       report_error_detected);
+
+       if (severity == AER_FATAL) {
+               result = reset_link(aerdev, dev);
+               if (result != PCI_ERS_RESULT_RECOVERED) {
+                       /* TODO: Should panic here? */
+                       return result;
+               }
+       }
+
+       if (status == PCI_ERS_RESULT_CAN_RECOVER)
+               status = broadcast_error_message(dev,
+                               state,
+                               "mmio_enabled",
+                               report_mmio_enabled);
+
+       if (status == PCI_ERS_RESULT_NEED_RESET) {
+               /*
+                * TODO: Should call platform-specific
+                * functions to reset slot before calling
+                * drivers' slot_reset callbacks?
+                */
+               status = broadcast_error_message(dev,
+                               state,
+                               "slot_reset",
+                               report_slot_reset);
+       }
+
+       if (status == PCI_ERS_RESULT_RECOVERED)
+               broadcast_error_message(dev,
+                               state,
+                               "resume",
+                               report_resume);
+
+       return status;
+}
+
+/**
+ * handle_error_source - handle logging error into an event log
+ * @aerdev: pointer to pcie_device data structure of the root port
+ * @dev: pointer to pci_dev data structure of error source device
+ * @info: comprehensive error information
+ *
+ * Invoked when an error being detected by Root Port.
+ **/
+static void handle_error_source(struct pcie_device * aerdev,
+       struct pci_dev *dev,
+       struct aer_err_info info)
+{
+       pci_ers_result_t status = 0;
+       int pos;
+
+       if (info.severity == AER_CORRECTABLE) {
+               /*
+                * Correctable error does not need software intevention.
+                * No need to go through error recovery process.
+                */
+               pos = pci_find_aer_capability(dev);
+               if (pos)
+                       pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
+                                       info.status);
+       } else {
+               status = do_recovery(aerdev, dev, info.severity);
+               if (status == PCI_ERS_RESULT_RECOVERED) {
+                       printk(KERN_DEBUG "AER driver successfully recovered\n");
+               } else {
+                       /* TODO: Should kernel panic here? */
+                       printk(KERN_DEBUG "AER driver didn't recover\n");
+               }
+       }
+}
+
+/**
+ * aer_enable_rootport - enable Root Port's interrupts when receiving messages
+ * @rpc: pointer to a Root Port data structure
+ *
+ * Invoked when PCIE bus loads AER service driver.
+ **/
+void aer_enable_rootport(struct aer_rpc *rpc)
+{
+       struct pci_dev *pdev = rpc->rpd->port;
+       int pos, aer_pos;
+       u16 reg16;
+       u32 reg32;
+
+       pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+       /* Clear PCIE Capability's Device Status */
+       pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, &reg16);
+       pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16);
+
+       /* Disable system error generation in response to error messages */
+       pci_read_config_word(pdev, pos + PCI_EXP_RTCTL, &reg16);
+       reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK);
+       pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16);
+
+       aer_pos = pci_find_aer_capability(pdev);
+       /* Clear error status */
+       pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
+       pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
+       pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
+       pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
+       pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
+       pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
+
+       /* Enable Root Port device reporting error itself */
+       pci_read_config_word(pdev, pos+PCI_EXP_DEVCTL, &reg16);
+       reg16 = reg16 |
+               PCI_EXP_DEVCTL_CERE |
+               PCI_EXP_DEVCTL_NFERE |
+               PCI_EXP_DEVCTL_FERE |
+               PCI_EXP_DEVCTL_URRE;
+       pci_write_config_word(pdev, pos+PCI_EXP_DEVCTL,
+               reg16);
+
+       /* Enable Root Port's interrupt in response to error messages */
+       pci_write_config_dword(pdev,
+               aer_pos + PCI_ERR_ROOT_COMMAND,
+               ROOT_PORT_INTR_ON_MESG_MASK);
+}
+
+/**
+ * disable_root_aer - disable Root Port's interrupts when receiving messages
+ * @rpc: pointer to a Root Port data structure
+ *
+ * Invoked when PCIE bus unloads AER service driver.
+ **/
+static void disable_root_aer(struct aer_rpc *rpc)
+{
+       struct pci_dev *pdev = rpc->rpd->port;
+       u32 reg32;
+       int pos;
+
+       pos = pci_find_aer_capability(pdev);
+       /* Disable Root's interrupt in response to error messages */
+       pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, 0);
+
+       /* Clear Root's error status reg */
+       pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
+       pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
+}
+
+/**
+ * get_e_source - retrieve an error source
+ * @rpc: pointer to the root port which holds an error
+ *
+ * Invoked by DPC handler to consume an error.
+ **/
+static struct aer_err_source* get_e_source(struct aer_rpc *rpc)
+{
+       struct aer_err_source *e_source;
+       unsigned long flags;
+
+       /* Lock access to Root error producer/consumer index */
+       spin_lock_irqsave(&rpc->e_lock, flags);
+       if (rpc->prod_idx == rpc->cons_idx) {
+               spin_unlock_irqrestore(&rpc->e_lock, flags);
+               return NULL;
+       }
+       e_source = &rpc->e_sources[rpc->cons_idx];
+       rpc->cons_idx++;
+       if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
+               rpc->cons_idx = 0;
+       spin_unlock_irqrestore(&rpc->e_lock, flags);
+
+       return e_source;
+}
+
+static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
+{
+       int pos;
+
+       pos = pci_find_aer_capability(dev);
+
+       /* The device might not support AER */
+       if (!pos)
+               return AER_SUCCESS;
+
+       if (info->severity == AER_CORRECTABLE) {
+               pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS,
+                       &info->status);
+               if (!(info->status & ERR_CORRECTABLE_ERROR_MASK))
+                       return AER_UNSUCCESS;
+       } else if (dev->hdr_type & PCI_HEADER_TYPE_BRIDGE ||
+               info->severity == AER_NONFATAL) {
+
+               /* Link is still healthy for IO reads */
+               pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
+                       &info->status);
+               if (!(info->status & ERR_UNCORRECTABLE_ERROR_MASK))
+                       return AER_UNSUCCESS;
+
+               if (info->status & AER_LOG_TLP_MASKS) {
+                       info->flags |= AER_TLP_HEADER_VALID_FLAG;
+                       pci_read_config_dword(dev,
+                               pos + PCI_ERR_HEADER_LOG, &info->tlp.dw0);
+                       pci_read_config_dword(dev,
+                               pos + PCI_ERR_HEADER_LOG + 4, &info->tlp.dw1);
+                       pci_read_config_dword(dev,
+                               pos + PCI_ERR_HEADER_LOG + 8, &info->tlp.dw2);
+                       pci_read_config_dword(dev,
+                               pos + PCI_ERR_HEADER_LOG + 12, &info->tlp.dw3);
+               }
+       }
+
+       return AER_SUCCESS;
+}
+
+/**
+ * aer_isr_one_error - consume an error detected by root port
+ * @p_device: pointer to error root port service device
+ * @e_src: pointer to an error source
+ **/
+static void aer_isr_one_error(struct pcie_device *p_device,
+               struct aer_err_source *e_src)
+{
+       struct device *s_device;
+       struct aer_err_info e_info = {0, 0, 0,};
+       int i;
+       u16 id;
+
+       /*
+        * There is a possibility that both correctable error and
+        * uncorrectable error being logged. Report correctable error first.
+        */
+       for (i = 1; i & ROOT_ERR_STATUS_MASKS ; i <<= 2) {
+               if (i > 4)
+                       break;
+               if (!(e_src->status & i))
+                       continue;
+
+               /* Init comprehensive error information */
+               if (i & PCI_ERR_ROOT_COR_RCV) {
+                       id = ERR_COR_ID(e_src->id);
+                       e_info.severity = AER_CORRECTABLE;
+               } else {
+                       id = ERR_UNCOR_ID(e_src->id);
+                       e_info.severity = ((e_src->status >> 6) & 1);
+               }
+               if (e_src->status &
+                       (PCI_ERR_ROOT_MULTI_COR_RCV |
+                        PCI_ERR_ROOT_MULTI_UNCOR_RCV))
+                       e_info.flags |= AER_MULTI_ERROR_VALID_FLAG;
+               if (!(s_device = find_source_device(p_device->port, id))) {
+                       printk(KERN_DEBUG "%s->can't find device of ID%04x\n",
+                               __FUNCTION__, id);
+                       continue;
+               }
+               if (get_device_error_info(to_pci_dev(s_device), &e_info) ==
+                               AER_SUCCESS) {
+                       aer_print_error(to_pci_dev(s_device), &e_info);
+                       handle_error_source(p_device,
+                               to_pci_dev(s_device),
+                               e_info);
+               }
+       }
+}
+
+/**
+ * aer_isr - consume errors detected by root port
+ * @context: pointer to a private data of pcie device
+ *
+ * Invoked, as DPC, when root port records new detected error
+ **/
+void aer_isr(void *context)
+{
+       struct pcie_device *p_device = (struct pcie_device *) context;
+       struct aer_rpc *rpc = get_service_data(p_device);
+       struct aer_err_source *e_src;
+
+       mutex_lock(&rpc->rpc_mutex);
+       e_src = get_e_source(rpc);
+       while (e_src) {
+               aer_isr_one_error(p_device, e_src);
+               e_src = get_e_source(rpc);
+       }
+       mutex_unlock(&rpc->rpc_mutex);
+
+       wake_up(&rpc->wait_release);
+}
+
+/**
+ * aer_delete_rootport - disable root port aer and delete service data
+ * @rpc: pointer to a root port device being deleted
+ *
+ * Invoked when AER service unloaded on a specific Root Port
+ **/
+void aer_delete_rootport(struct aer_rpc *rpc)
+{
+       /* Disable root port AER itself */
+       disable_root_aer(rpc);
+
+       kfree(rpc);
+}
+
+/**
+ * aer_init - provide AER initialization
+ * @dev: pointer to AER pcie device
+ *
+ * Invoked when AER service driver is loaded.
+ **/
+int aer_init(struct pcie_device *dev)
+{
+       int status;
+
+       /* Run _OSC Method */
+       status = aer_osc_setup(dev->port);
+
+       if(status != OSC_METHOD_RUN_SUCCESS) {
+               printk(KERN_DEBUG "%s: AER service init fails - %s\n",
+               __FUNCTION__,
+               (status == OSC_METHOD_NOT_SUPPORTED) ?
+                       "No ACPI _OSC support" : "Run ACPI _OSC fails");
+
+               if (!forceload)
+                       return status;
+       }
+
+       return AER_SUCCESS;
+}
+
+EXPORT_SYMBOL_GPL(pci_find_aer_capability);
+EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
+EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
+EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
+
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
new file mode 100644 (file)
index 0000000..3933d4f
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * drivers/pci/pcie/aer/aerdrv_errprint.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Format error messages and print them to console.
+ *
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/suspend.h>
+
+#include "aerdrv.h"
+
+#define AER_AGENT_RECEIVER             0
+#define AER_AGENT_REQUESTER            1
+#define AER_AGENT_COMPLETER            2
+#define AER_AGENT_TRANSMITTER          3
+
+#define AER_AGENT_REQUESTER_MASK       (PCI_ERR_UNC_COMP_TIME| \
+                                       PCI_ERR_UNC_UNSUP)
+
+#define AER_AGENT_COMPLETER_MASK       PCI_ERR_UNC_COMP_ABORT
+
+#define AER_AGENT_TRANSMITTER_MASK(t, e) (e & (PCI_ERR_COR_REP_ROLL| \
+       ((t == AER_CORRECTABLE) ? PCI_ERR_COR_REP_TIMER: 0)))
+
+#define AER_GET_AGENT(t, e)                                            \
+       ((e & AER_AGENT_COMPLETER_MASK) ? AER_AGENT_COMPLETER :         \
+       (e & AER_AGENT_REQUESTER_MASK) ? AER_AGENT_REQUESTER :          \
+       (AER_AGENT_TRANSMITTER_MASK(t, e)) ? AER_AGENT_TRANSMITTER :    \
+       AER_AGENT_RECEIVER)
+
+#define AER_PHYSICAL_LAYER_ERROR_MASK  PCI_ERR_COR_RCVR
+#define AER_DATA_LINK_LAYER_ERROR_MASK(t, e)   \
+               (PCI_ERR_UNC_DLP|               \
+               PCI_ERR_COR_BAD_TLP|            \
+               PCI_ERR_COR_BAD_DLLP|           \
+               PCI_ERR_COR_REP_ROLL|           \
+               ((t == AER_CORRECTABLE) ?       \
+               PCI_ERR_COR_REP_TIMER: 0))
+
+#define AER_PHYSICAL_LAYER_ERROR       0
+#define AER_DATA_LINK_LAYER_ERROR      1
+#define AER_TRANSACTION_LAYER_ERROR    2
+
+#define AER_GET_LAYER_ERROR(t, e)                              \
+       ((e & AER_PHYSICAL_LAYER_ERROR_MASK) ?                  \
+       AER_PHYSICAL_LAYER_ERROR :                              \
+       (e & AER_DATA_LINK_LAYER_ERROR_MASK(t, e)) ?            \
+               AER_DATA_LINK_LAYER_ERROR :                     \
+               AER_TRANSACTION_LAYER_ERROR)
+
+/*
+ * AER error strings
+ */
+static char* aer_error_severity_string[] = {
+       "Uncorrected (Non-Fatal)",
+       "Uncorrected (Fatal)",
+       "Corrected"
+};
+
+static char* aer_error_layer[] = {
+       "Physical Layer",
+       "Data Link Layer",
+       "Transaction Layer"
+};
+static char* aer_correctable_error_string[] = {
+       "Receiver Error        ",       /* Bit Position 0       */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "Bad TLP               ",       /* Bit Position 6       */
+       "Bad DLLP              ",       /* Bit Position 7       */
+       "RELAY_NUM Rollover    ",       /* Bit Position 8       */
+       NULL,
+       NULL,
+       NULL,
+       "Replay Timer Timeout  ",       /* Bit Position 12      */
+       "Advisory Non-Fatal    ",       /* Bit Position 13      */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+};
+
+static char* aer_uncorrectable_error_string[] = {
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "Data Link Protocol    ",       /* Bit Position 4       */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "Poisoned TLP          ",       /* Bit Position 12      */
+       "Flow Control Protocol ",       /* Bit Position 13      */
+       "Completion Timeout    ",       /* Bit Position 14      */
+       "Completer Abort       ",       /* Bit Position 15      */
+       "Unexpected Completion ",       /* Bit Position 16      */
+       "Receiver Overflow     ",       /* Bit Position 17      */
+       "Malformed TLP         ",       /* Bit Position 18      */
+       "ECRC                  ",       /* Bit Position 19      */
+       "Unsupported Request   ",       /* Bit Position 20      */
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+};
+
+static char* aer_agent_string[] = {
+       "Receiver ID",
+       "Requester ID",
+       "Completer ID",
+       "Transmitter ID"
+};
+
+static char * aer_get_error_source_name(int severity,
+                       unsigned int status,
+                       char errmsg_buff[])
+{
+       int i;
+       char * errmsg = NULL;
+
+       for (i = 0; i < 32; i++) {
+               if (!(status & (1 << i)))
+                       continue;
+
+               if (severity == AER_CORRECTABLE)
+                       errmsg = aer_correctable_error_string[i];
+               else
+                       errmsg = aer_uncorrectable_error_string[i];
+
+               if (!errmsg) {
+                       sprintf(errmsg_buff, "Unknown Error Bit %2d  ", i);
+                       errmsg = errmsg_buff;
+               }
+
+               break;
+       }
+
+       return errmsg;
+}
+
+static DEFINE_SPINLOCK(logbuf_lock);
+static char errmsg_buff[100];
+void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
+{
+       char * errmsg;
+       int err_layer, agent;
+       char * loglevel;
+
+       if (info->severity == AER_CORRECTABLE)
+               loglevel = KERN_WARNING;
+       else
+               loglevel = KERN_ERR;
+
+       printk("%s+------ PCI-Express Device Error ------+\n", loglevel);
+       printk("%sError Severity\t\t: %s\n", loglevel,
+               aer_error_severity_string[info->severity]);
+
+       if ( info->status == 0) {
+               printk("%sPCIE Bus Error type\t: (Unaccessible)\n", loglevel);
+               printk("%sUnaccessible Received\t: %s\n", loglevel,
+                       info->flags & AER_MULTI_ERROR_VALID_FLAG ?
+                               "Multiple" : "First");
+               printk("%sUnregistered Agent ID\t: %04x\n", loglevel,
+                       (dev->bus->number << 8) | dev->devfn);
+       } else {
+               err_layer = AER_GET_LAYER_ERROR(info->severity, info->status);
+               printk("%sPCIE Bus Error type\t: %s\n", loglevel,
+                       aer_error_layer[err_layer]);
+
+               spin_lock(&logbuf_lock);
+               errmsg = aer_get_error_source_name(info->severity,
+                               info->status,
+                               errmsg_buff);
+               printk("%s%s\t: %s\n", loglevel, errmsg,
+                       info->flags & AER_MULTI_ERROR_VALID_FLAG ?
+                               "Multiple" : "First");
+               spin_unlock(&logbuf_lock);
+
+               agent = AER_GET_AGENT(info->severity, info->status);
+               printk("%s%s\t\t: %04x\n", loglevel,
+                       aer_agent_string[agent],
+                       (dev->bus->number << 8) | dev->devfn);
+
+               printk("%sVendorID=%04xh, DeviceID=%04xh,"
+                       " Bus=%02xh, Device=%02xh, Function=%02xh\n",
+                       loglevel,
+                       dev->vendor,
+                       dev->device,
+                       dev->bus->number,
+                       PCI_SLOT(dev->devfn),
+                       PCI_FUNC(dev->devfn));
+
+               if (info->flags & AER_TLP_HEADER_VALID_FLAG) {
+                       unsigned char *tlp = (unsigned char *) &info->tlp;
+                       printk("%sTLB Header:\n", loglevel);
+                       printk("%s%02x%02x%02x%02x %02x%02x%02x%02x"
+                               " %02x%02x%02x%02x %02x%02x%02x%02x\n",
+                               loglevel,
+                               *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
+                               *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
+                               *(tlp + 11), *(tlp + 10), *(tlp + 9),
+                               *(tlp + 8), *(tlp + 15), *(tlp + 14),
+                               *(tlp + 13), *(tlp + 12));
+               }
+       }
+}
+
index 1d317d22ee892f0dd17efc2b4814c9a9e642a4a1..67fcd176babdb8182242d9d038f5b665364654d6 100644 (file)
@@ -39,7 +39,7 @@ extern int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state);
 extern int pcie_port_device_resume(struct pci_dev *dev);
 #endif
 extern void pcie_port_device_remove(struct pci_dev *dev);
-extern void pcie_port_bus_register(void);
+extern int pcie_port_bus_register(void);
 extern void pcie_port_bus_unregister(void);
 
 #endif /* _PORTDRV_H_ */
index 3e84b501e6a419ea2b7e28452983c36a8a127bff..3f0976868eda656c9a2441caae804c96f9cc3fac 100644 (file)
@@ -24,6 +24,7 @@ struct bus_type pcie_port_bus_type = {
        .suspend        = pcie_port_bus_suspend,
        .resume         = pcie_port_bus_resume, 
 };
+EXPORT_SYMBOL_GPL(pcie_port_bus_type);
 
 static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
 {
index 55c66226786887e27640285d6167980c2df155aa..bd6615b4d40eb7546521a41898b39bd3a0da47d1 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
  */
 
+#include <linux/compiler.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -339,8 +340,7 @@ static int suspend_iter(struct device *dev, void *data)
 
 int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state)
 {
-       device_for_each_child(&dev->dev, &state, suspend_iter);
-       return 0;
+       return device_for_each_child(&dev->dev, &state, suspend_iter);
 }
 
 static int resume_iter(struct device *dev, void *data)
@@ -358,8 +358,7 @@ static int resume_iter(struct device *dev, void *data)
 
 int pcie_port_device_resume(struct pci_dev *dev)
 {
-       device_for_each_child(&dev->dev, NULL, resume_iter);
-       return 0;
+       return device_for_each_child(&dev->dev, NULL, resume_iter);
 }
 #endif
 
@@ -402,9 +401,9 @@ void pcie_port_device_remove(struct pci_dev *dev)
                pci_disable_msi(dev);
 }
 
-void pcie_port_bus_register(void)
+int __must_check pcie_port_bus_register(void)
 {
-       bus_register(&pcie_port_bus_type);
+       return bus_register(&pcie_port_bus_type);
 }
 
 void pcie_port_bus_unregister(void)
index 478d0d28f7ad1e6b573e5e3c3a26f37b9dc1e557..037690e08f5f023a0e012806efbe9627b2450c7c 100644 (file)
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/pcieport_if.h>
+#include <linux/aer.h>
 
 #include "portdrv.h"
+#include "aer/aerdrv.h"
 
 /*
  * Version Information
@@ -30,6 +32,43 @@ MODULE_LICENSE("GPL");
 /* global data */
 static const char device_name[] = "pcieport-driver";
 
+static int pcie_portdrv_save_config(struct pci_dev *dev)
+{
+       return pci_save_state(dev);
+}
+
+#ifdef CONFIG_PM
+static int pcie_portdrv_restore_config(struct pci_dev *dev)
+{
+       int retval;
+
+       pci_restore_state(dev);
+       retval = pci_enable_device(dev);
+       if (retval)
+               return retval;
+       pci_set_master(dev);
+       return 0;
+}
+
+static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state)
+{
+       int ret = pcie_port_device_suspend(dev, state);
+
+       if (!ret)
+               ret = pcie_portdrv_save_config(dev);
+       return ret;
+}
+
+static int pcie_portdrv_resume(struct pci_dev *dev)
+{
+       pcie_portdrv_restore_config(dev);
+       return pcie_port_device_resume(dev);
+}
+#else
+#define pcie_portdrv_suspend NULL
+#define pcie_portdrv_resume NULL
+#endif
+
 /*
  * pcie_portdrv_probe - Probe PCI-Express port devices
  * @dev: PCI-Express port device being probed
@@ -61,6 +100,10 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
                return -ENOMEM;
        }
 
+       pcie_portdrv_save_config(dev);
+
+       pci_enable_pcie_error_reporting(dev);
+
        return 0;
 }
 
@@ -70,39 +113,151 @@ static void pcie_portdrv_remove (struct pci_dev *dev)
        kfree(pci_get_drvdata(dev));
 }
 
-#ifdef CONFIG_PM
-static int pcie_portdrv_save_config(struct pci_dev *dev)
+static int error_detected_iter(struct device *device, void *data)
 {
-       return pci_save_state(dev);
+       struct pcie_device *pcie_device;
+       struct pcie_port_service_driver *driver;
+       struct aer_broadcast_data *result_data;
+       pci_ers_result_t status;
+
+       result_data = (struct aer_broadcast_data *) data;
+
+       if (device->bus == &pcie_port_bus_type && device->driver) {
+               driver = to_service_driver(device->driver);
+               if (!driver ||
+                       !driver->err_handler ||
+                       !driver->err_handler->error_detected)
+                       return 0;
+
+               pcie_device = to_pcie_device(device);
+
+               /* Forward error detected message to service drivers */
+               status = driver->err_handler->error_detected(
+                       pcie_device->port,
+                       result_data->state);
+               result_data->result =
+                       merge_result(result_data->result, status);
+       }
+
+       return 0;
 }
 
-static int pcie_portdrv_restore_config(struct pci_dev *dev)
+static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev,
+                                       enum pci_channel_state error)
 {
+       struct aer_broadcast_data result_data =
+                       {error, PCI_ERS_RESULT_CAN_RECOVER};
        int retval;
 
-       pci_restore_state(dev);
-       retval = pci_enable_device(dev);
-       if (retval)
-               return retval;
-       pci_set_master(dev);
+       /* can not fail */
+       retval = device_for_each_child(&dev->dev, &result_data, error_detected_iter);
+
+       return result_data.result;
+}
+
+static int mmio_enabled_iter(struct device *device, void *data)
+{
+       struct pcie_device *pcie_device;
+       struct pcie_port_service_driver *driver;
+       pci_ers_result_t status, *result;
+
+       result = (pci_ers_result_t *) data;
+
+       if (device->bus == &pcie_port_bus_type && device->driver) {
+               driver = to_service_driver(device->driver);
+               if (driver &&
+                       driver->err_handler &&
+                       driver->err_handler->mmio_enabled) {
+                       pcie_device = to_pcie_device(device);
+
+                       /* Forward error message to service drivers */
+                       status = driver->err_handler->mmio_enabled(
+                                       pcie_device->port);
+                       *result = merge_result(*result, status);
+               }
+       }
+
        return 0;
 }
 
-static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state)
+static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev)
 {
-       int ret = pcie_port_device_suspend(dev, state);
+       pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED;
+       int retval;
 
-       if (!ret)
-               ret = pcie_portdrv_save_config(dev);
-       return ret;
+       /* get true return value from &status */
+       retval = device_for_each_child(&dev->dev, &status, mmio_enabled_iter);
+       return status;
 }
 
-static int pcie_portdrv_resume (struct pci_dev *dev)
+static int slot_reset_iter(struct device *device, void *data)
 {
-       pcie_portdrv_restore_config(dev);
-       return pcie_port_device_resume(dev);
+       struct pcie_device *pcie_device;
+       struct pcie_port_service_driver *driver;
+       pci_ers_result_t status, *result;
+
+       result = (pci_ers_result_t *) data;
+
+       if (device->bus == &pcie_port_bus_type && device->driver) {
+               driver = to_service_driver(device->driver);
+               if (driver &&
+                       driver->err_handler &&
+                       driver->err_handler->slot_reset) {
+                       pcie_device = to_pcie_device(device);
+
+                       /* Forward error message to service drivers */
+                       status = driver->err_handler->slot_reset(
+                                       pcie_device->port);
+                       *result = merge_result(*result, status);
+               }
+       }
+
+       return 0;
+}
+
+static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev)
+{
+       pci_ers_result_t status;
+       int retval;
+
+       /* If fatal, restore cfg space for possible link reset at upstream */
+       if (dev->error_state == pci_channel_io_frozen) {
+               pcie_portdrv_restore_config(dev);
+               pci_enable_pcie_error_reporting(dev);
+       }
+
+       /* get true return value from &status */
+       retval = device_for_each_child(&dev->dev, &status, slot_reset_iter);
+
+       return status;
+}
+
+static int resume_iter(struct device *device, void *data)
+{
+       struct pcie_device *pcie_device;
+       struct pcie_port_service_driver *driver;
+
+       if (device->bus == &pcie_port_bus_type && device->driver) {
+               driver = to_service_driver(device->driver);
+               if (driver &&
+                       driver->err_handler &&
+                       driver->err_handler->resume) {
+                       pcie_device = to_pcie_device(device);
+
+                       /* Forward error message to service drivers */
+                       driver->err_handler->resume(pcie_device->port);
+               }
+       }
+
+       return 0;
+}
+
+static void pcie_portdrv_err_resume(struct pci_dev *dev)
+{
+       int retval;
+       /* nothing to do with error value, if it ever happens */
+       retval = device_for_each_child(&dev->dev, NULL, resume_iter);
 }
-#endif
 
 /*
  * LINUX Device Driver Model
@@ -114,6 +269,13 @@ static const struct pci_device_id port_pci_ids[] = { {
 };
 MODULE_DEVICE_TABLE(pci, port_pci_ids);
 
+static struct pci_error_handlers pcie_portdrv_err_handler = {
+               .error_detected = pcie_portdrv_error_detected,
+               .mmio_enabled = pcie_portdrv_mmio_enabled,
+               .slot_reset = pcie_portdrv_slot_reset,
+               .resume = pcie_portdrv_err_resume,
+};
+
 static struct pci_driver pcie_portdrv = {
        .name           = (char *)device_name,
        .id_table       = &port_pci_ids[0],
@@ -121,20 +283,25 @@ static struct pci_driver pcie_portdrv = {
        .probe          = pcie_portdrv_probe,
        .remove         = pcie_portdrv_remove,
 
-#ifdef CONFIG_PM
        .suspend        = pcie_portdrv_suspend,
        .resume         = pcie_portdrv_resume,
-#endif /* PM */
+
+       .err_handler    = &pcie_portdrv_err_handler,
 };
 
 static int __init pcie_portdrv_init(void)
 {
-       int retval = 0;
+       int retval;
 
-       pcie_port_bus_register();
+       retval = pcie_port_bus_register();
+       if (retval) {
+               printk(KERN_WARNING "PCIE: bus_register error: %d\n", retval);
+               goto out;
+       }
        retval = pci_register_driver(&pcie_portdrv);
        if (retval)
                pcie_port_bus_unregister();
+ out:
        return retval;
 }
 
index c5a58d1c6c1c14f266d5d45d8f980e9531f37db0..a3b0a5eb5054fefcc0e76e72b838fac1146fd310 100644 (file)
@@ -339,6 +339,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
 {
        struct pci_bus *child;
        int i;
+       int retval;
 
        /*
         * Allocate a new bus, and inherit stuff from the parent..
@@ -356,8 +357,13 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
 
        child->class_dev.class = &pcibus_class;
        sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr);
-       class_device_register(&child->class_dev);
-       class_device_create_file(&child->class_dev, &class_device_attr_cpuaffinity);
+       retval = class_device_register(&child->class_dev);
+       if (retval)
+               goto error_register;
+       retval = class_device_create_file(&child->class_dev,
+                                         &class_device_attr_cpuaffinity);
+       if (retval)
+               goto error_file_create;
 
        /*
         * Set up the primary, secondary and subordinate
@@ -375,6 +381,12 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
        bridge->subordinate = child;
 
        return child;
+
+error_file_create:
+       class_device_unregister(&child->class_dev);
+error_register:
+       kfree(child);
+       return NULL;
 }
 
 struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
index def78a2a7c156a2b7ef40041ca7a2558a8ac0a6b..08cd86a6dd6696585dc5937d1b056a55e898d6a0 100644 (file)
@@ -577,8 +577,6 @@ static void __init quirk_ioapic_rmw(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,      PCI_ANY_ID,                     quirk_ioapic_rmw );
 
-int pci_msi_quirk;
-
 #define AMD8131_revA0        0x01
 #define AMD8131_revB0        0x11
 #define AMD8131_MISC         0x40
@@ -587,12 +585,6 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
 { 
         unsigned char revid, tmp;
         
-       if (dev->subordinate) {
-               printk(KERN_WARNING "PCI: MSI quirk detected. "
-                      "PCI_BUS_FLAGS_NO_MSI set for subordinate bus.\n");
-               dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
-       }
-
         if (nr_ioapics == 0) 
                 return;
 
@@ -605,13 +597,6 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
         }
 } 
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_amd_8131_ioapic);
-
-static void __init quirk_svw_msi(struct pci_dev *dev)
-{
-       pci_msi_quirk = 1;
-       printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
-}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi );
 #endif /* CONFIG_X86_IO_APIC */
 
 
@@ -1690,6 +1675,95 @@ static void __devinit quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA,  PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
                        quirk_nvidia_ck804_pcie_aer_ext_cap);
 
+#ifdef CONFIG_PCI_MSI
+/* To disable MSI globally */
+int pci_msi_quirk;
+
+/* The Serverworks PCI-X chipset does not support MSI. We cannot easily rely
+ * on setting PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
+ * some other busses controlled by the chipset even if Linux is not aware of it.
+ * Instead of setting the flag on all busses in the machine, simply disable MSI
+ * globally.
+ */
+static void __init quirk_svw_msi(struct pci_dev *dev)
+{
+       pci_msi_quirk = 1;
+       printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi);
+
+/* Disable MSI on chipsets that are known to not support it */
+static void __devinit quirk_disable_msi(struct pci_dev *dev)
+{
+       if (dev->subordinate) {
+               printk(KERN_WARNING "PCI: MSI quirk detected. "
+                      "PCI_BUS_FLAGS_NO_MSI set for %s subordinate bus.\n",
+                      pci_name(dev));
+               dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);
+
+/* Go through the list of Hypertransport capabilities and
+ * return 1 if a HT MSI capability is found and enabled */
+static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
+{
+       u8 pos;
+       int ttl;
+       for (pos = pci_find_capability(dev, PCI_CAP_ID_HT), ttl = 48;
+            pos && ttl;
+            pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_HT), ttl--) {
+               u32 cap_hdr;
+               /* MSI mapping section according to Hypertransport spec */
+               if (pci_read_config_dword(dev, pos, &cap_hdr) == 0
+                   && (cap_hdr & 0xf8000000) == 0xa8000000 /* MSI mapping */) {
+                       printk(KERN_INFO "PCI: Found HT MSI mapping on %s with capability %s\n",
+                              pci_name(dev), cap_hdr & 0x10000 ? "enabled" : "disabled");
+                       return (cap_hdr & 0x10000) != 0; /* MSI mapping cap enabled */
+               }
+       }
+       return 0;
+}
+
+/* Check the hypertransport MSI mapping to know whether MSI is enabled or not */
+static void __devinit quirk_msi_ht_cap(struct pci_dev *dev)
+{
+       if (dev->subordinate && !msi_ht_cap_enabled(dev)) {
+               printk(KERN_WARNING "PCI: MSI quirk detected. "
+                      "MSI disabled on chipset %s.\n",
+                      pci_name(dev));
+               dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE,
+                       quirk_msi_ht_cap);
+
+/* The nVidia CK804 chipset may have 2 HT MSI mappings.
+ * MSI are supported if the MSI capability set in any of these mappings.
+ */
+static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
+{
+       struct pci_dev *pdev;
+
+       if (!dev->subordinate)
+               return;
+
+       /* check HT MSI cap on this chipset and the root one.
+        * a single one having MSI is enough to be sure that MSI are supported.
+        */
+       pdev = pci_find_slot(dev->bus->number, 0);
+       if (dev->subordinate && !msi_ht_cap_enabled(dev)
+           && !msi_ht_cap_enabled(pdev)) {
+               printk(KERN_WARNING "PCI: MSI quirk detected. "
+                      "MSI disabled on chipset %s.\n",
+                      pci_name(dev));
+               dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
+                       quirk_nvidia_ck804_msi_ht_cap);
+#endif /* CONFIG_PCI_MSI */
+
 EXPORT_SYMBOL(pcie_mch_quirk);
 #ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pci_fixup_device);
index 99ffbd478b29c5ffd74d4593ddab6625b2b7fc9d..430281b2e9212400af4b8bf3dd9aa1fa72c41855 100644 (file)
@@ -16,8 +16,11 @@ static void pci_free_resources(struct pci_dev *dev)
        }
 }
 
-static void pci_destroy_dev(struct pci_dev *dev)
+static void pci_stop_dev(struct pci_dev *dev)
 {
+       if (!dev->global_list.next)
+               return;
+
        if (!list_empty(&dev->global_list)) {
                pci_proc_detach_device(dev);
                pci_remove_sysfs_dev_files(dev);
@@ -27,6 +30,11 @@ static void pci_destroy_dev(struct pci_dev *dev)
                dev->global_list.next = dev->global_list.prev = NULL;
                up_write(&pci_bus_sem);
        }
+}
+
+static void pci_destroy_dev(struct pci_dev *dev)
+{
+       pci_stop_dev(dev);
 
        /* Remove the device from the device lists, and prevent any further
         * list accesses from this device */
@@ -119,5 +127,32 @@ void pci_remove_behind_bridge(struct pci_dev *dev)
        }
 }
 
+static void pci_stop_bus_devices(struct pci_bus *bus)
+{
+       struct list_head *l, *n;
+
+       list_for_each_safe(l, n, &bus->devices) {
+               struct pci_dev *dev = pci_dev_b(l);
+               pci_stop_bus_device(dev);
+       }
+}
+
+/**
+ * pci_stop_bus_device - stop a PCI device and any children
+ * @dev: the device to stop
+ *
+ * Stop a PCI device (detach the driver, remove from the global list
+ * and so on). This also stop any subordinate buses and children in a
+ * depth-first manner.
+ */
+void pci_stop_bus_device(struct pci_dev *dev)
+{
+       if (dev->subordinate)
+               pci_stop_bus_devices(dev->subordinate);
+
+       pci_stop_dev(dev);
+}
+
 EXPORT_SYMBOL(pci_remove_bus_device);
 EXPORT_SYMBOL(pci_remove_behind_bridge);
+EXPORT_SYMBOL_GPL(pci_stop_bus_device);
index 47c1071ad84ea06b057faac42e6ea60aeb87c5fe..54404917be9a5ebbaaa77d694d118eba1298a7d3 100644 (file)
@@ -55,12 +55,19 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
        list_for_each_entry(dev, &bus->devices, bus_list) {
                u16 class = dev->class >> 8;
 
-               /* Don't touch classless devices or host bridges or ioapics.  */
+               /* Don't touch classless devices or host bridges. */
                if (class == PCI_CLASS_NOT_DEFINED ||
-                   class == PCI_CLASS_BRIDGE_HOST ||
-                   class == PCI_CLASS_SYSTEM_PIC)
+                   class == PCI_CLASS_BRIDGE_HOST)
                        continue;
 
+               /* Don't touch ioapics if it has the assigned resources. */
+               if (class == PCI_CLASS_SYSTEM_PIC) {
+                       res = &dev->resource[0];
+                       if (res[0].start || res[1].start || res[2].start ||
+                           res[3].start || res[4].start || res[5].start)
+                               continue;
+               }
+
                pdev_sort_resources(dev, &head);
        }
 
index 7ff1d88094b683b16827ea20b61804223ac5e85e..33a7b720539b081a8fabea5da18b06613565741d 100644 (file)
@@ -238,6 +238,16 @@ config RTC_DRV_SA1100
          To compile this driver as a module, choose M here: the
          module will be called rtc-sa1100.
 
+config RTC_DRV_SH
+       tristate "SuperH On-Chip RTC"
+       depends on RTC_CLASS && SUPERH
+       help
+         Say Y here to enable support for the on-chip RTC found in
+         most SuperH processors.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rtc-sh.
+
 config RTC_DRV_VR41XX
        tristate "NEC VR41XX"
        depends on RTC_CLASS && CPU_VR41XX
index bbcfb09d81d90398460a5316ce80817c67af186f..e72d467ab2143b771711c688933efda888306629 100644 (file)
@@ -31,3 +31,4 @@ obj-$(CONFIG_RTC_DRV_PL031)   += rtc-pl031.o
 obj-$(CONFIG_RTC_DRV_MAX6902)  += rtc-max6902.o
 obj-$(CONFIG_RTC_DRV_V3020)    += rtc-v3020.o
 obj-$(CONFIG_RTC_DRV_AT91)     += rtc-at91.o
+obj-$(CONFIG_RTC_DRV_SH)       += rtc-sh.o
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
new file mode 100644 (file)
index 0000000..d2ce0c8
--- /dev/null
@@ -0,0 +1,467 @@
+/*
+ * SuperH On-Chip RTC Support
+ *
+ * Copyright (C) 2006  Paul Mundt
+ *
+ * Based on the old arch/sh/kernel/cpu/rtc.c by:
+ *
+ *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
+ *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_CPU_SH3
+#define rtc_reg_size           sizeof(u16)
+#define RTC_BIT_INVERTED       0       /* No bug on SH7708, SH7709A */
+#elif defined(CONFIG_CPU_SH4)
+#define rtc_reg_size           sizeof(u32)
+#define RTC_BIT_INVERTED       0x40    /* bug on SH7750, SH7750S */
+#endif
+
+#define RTC_REG(r)     ((r) * rtc_reg_size)
+
+#define R64CNT         RTC_REG(0)
+#define RSECCNT        RTC_REG(1)
+#define RMINCNT        RTC_REG(2)
+#define RHRCNT         RTC_REG(3)
+#define RWKCNT         RTC_REG(4)
+#define RDAYCNT        RTC_REG(5)
+#define RMONCNT        RTC_REG(6)
+#define RYRCNT         RTC_REG(7)
+#define RSECAR         RTC_REG(8)
+#define RMINAR         RTC_REG(9)
+#define RHRAR          RTC_REG(10)
+#define RWKAR          RTC_REG(11)
+#define RDAYAR         RTC_REG(12)
+#define RMONAR         RTC_REG(13)
+#define RCR1           RTC_REG(14)
+#define RCR2           RTC_REG(15)
+
+/* RCR1 Bits */
+#define RCR1_CF                0x80    /* Carry Flag             */
+#define RCR1_CIE       0x10    /* Carry Interrupt Enable */
+#define RCR1_AIE       0x08    /* Alarm Interrupt Enable */
+#define RCR1_AF                0x01    /* Alarm Flag             */
+
+/* RCR2 Bits */
+#define RCR2_PEF       0x80    /* PEriodic interrupt Flag */
+#define RCR2_PESMASK   0x70    /* Periodic interrupt Set  */
+#define RCR2_RTCEN     0x08    /* ENable RTC              */
+#define RCR2_ADJ       0x04    /* ADJustment (30-second)  */
+#define RCR2_RESET     0x02    /* Reset bit               */
+#define RCR2_START     0x01    /* Start bit               */
+
+struct sh_rtc {
+       void __iomem *regbase;
+       unsigned long regsize;
+       struct resource *res;
+       unsigned int alarm_irq, periodic_irq, carry_irq;
+       struct rtc_device *rtc_dev;
+       spinlock_t lock;
+};
+
+static irqreturn_t sh_rtc_interrupt(int irq, void *id, struct pt_regs *regs)
+{
+       struct platform_device *pdev = id;
+       struct sh_rtc *rtc = platform_get_drvdata(pdev);
+       unsigned int tmp, events = 0;
+
+       spin_lock(&rtc->lock);
+
+       tmp = readb(rtc->regbase + RCR1);
+
+       if (tmp & RCR1_AF)
+               events |= RTC_AF | RTC_IRQF;
+
+       tmp &= ~(RCR1_CF | RCR1_AF);
+
+       writeb(tmp, rtc->regbase + RCR1);
+
+       rtc_update_irq(&rtc->rtc_dev->class_dev, 1, events);
+
+       spin_unlock(&rtc->lock);
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t sh_rtc_periodic(int irq, void *id, struct pt_regs *regs)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(id);
+
+       spin_lock(&rtc->lock);
+
+       rtc_update_irq(&rtc->rtc_dev->class_dev, 1, RTC_PF | RTC_IRQF);
+
+       spin_unlock(&rtc->lock);
+
+       return IRQ_HANDLED;
+}
+
+static inline void sh_rtc_setpie(struct device *dev, unsigned int enable)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(dev);
+       unsigned int tmp;
+
+       spin_lock_irq(&rtc->lock);
+
+       tmp = readb(rtc->regbase + RCR2);
+
+       if (enable) {
+               tmp &= ~RCR2_PESMASK;
+               tmp |= RCR2_PEF | (2 << 4);
+       } else
+               tmp &= ~(RCR2_PESMASK | RCR2_PEF);
+
+       writeb(tmp, rtc->regbase + RCR2);
+
+       spin_unlock_irq(&rtc->lock);
+}
+
+static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(dev);
+       unsigned int tmp;
+
+       spin_lock_irq(&rtc->lock);
+
+       tmp = readb(rtc->regbase + RCR1);
+
+       if (enable)
+               tmp |= RCR1_AIE;
+       else
+               tmp &= ~RCR1_AIE;
+
+       writeb(tmp, rtc->regbase + RCR1);
+
+       spin_unlock_irq(&rtc->lock);
+}
+
+static int sh_rtc_open(struct device *dev)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(dev);
+       unsigned int tmp;
+       int ret;
+
+       tmp = readb(rtc->regbase + RCR1);
+       tmp &= ~RCR1_CF;
+       tmp |= RCR1_CIE;
+       writeb(tmp, rtc->regbase + RCR1);
+
+       ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, SA_INTERRUPT,
+                         "sh-rtc period", dev);
+       if (unlikely(ret)) {
+               dev_err(dev, "request period IRQ failed with %d, IRQ %d\n",
+                       ret, rtc->periodic_irq);
+               return ret;
+       }
+
+       ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, SA_INTERRUPT,
+                         "sh-rtc carry", dev);
+       if (unlikely(ret)) {
+               dev_err(dev, "request carry IRQ failed with %d, IRQ %d\n",
+                       ret, rtc->carry_irq);
+               free_irq(rtc->periodic_irq, dev);
+               goto err_bad_carry;
+       }
+
+       ret = request_irq(rtc->alarm_irq, sh_rtc_interrupt, SA_INTERRUPT,
+                         "sh-rtc alarm", dev);
+       if (unlikely(ret)) {
+               dev_err(dev, "request alarm IRQ failed with %d, IRQ %d\n",
+                       ret, rtc->alarm_irq);
+               goto err_bad_alarm;
+       }
+
+       return 0;
+
+err_bad_alarm:
+       free_irq(rtc->carry_irq, dev);
+err_bad_carry:
+       free_irq(rtc->periodic_irq, dev);
+
+       return ret;
+}
+
+static void sh_rtc_release(struct device *dev)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(dev);
+
+       sh_rtc_setpie(dev, 0);
+
+       free_irq(rtc->periodic_irq, dev);
+       free_irq(rtc->carry_irq, dev);
+       free_irq(rtc->alarm_irq, dev);
+}
+
+static int sh_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+       struct sh_rtc *rtc = dev_get_drvdata(dev);
+       unsigned int tmp;
+
+       tmp = readb(rtc->regbase + RCR1);
+       seq_printf(seq, "alarm_IRQ\t: %s\n",
+                  (tmp & RCR1_AIE) ? "yes" : "no");
+       seq_printf(seq, "carry_IRQ\t: %s\n",
+                  (tmp & RCR1_CIE) ? "yes" : "no");
+
+       tmp = readb(rtc->regbase + RCR2);
+       seq_printf(seq, "periodic_IRQ\t: %s\n",
+                  (tmp & RCR2_PEF) ? "yes" : "no");
+
+       return 0;
+}
+
+static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+       unsigned int ret = -ENOIOCTLCMD;
+
+       switch (cmd) {
+       case RTC_PIE_OFF:
+       case RTC_PIE_ON:
+               sh_rtc_setpie(dev, cmd == RTC_PIE_ON);
+               ret = 0;
+               break;
+       case RTC_AIE_OFF:
+       case RTC_AIE_ON:
+               sh_rtc_setaie(dev, cmd == RTC_AIE_ON);
+               ret = 0;
+               break;
+       }
+
+       return ret;
+}
+
+static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_rtc *rtc = platform_get_drvdata(pdev);
+       unsigned int sec128, sec2, yr, yr100, cf_bit;
+
+       do {
+               unsigned int tmp;
+
+               spin_lock_irq(&rtc->lock);
+
+               tmp = readb(rtc->regbase + RCR1);
+               tmp &= ~RCR1_CF; /* Clear CF-bit */
+               tmp |= RCR1_CIE;
+               writeb(tmp, rtc->regbase + RCR1);
+
+               sec128 = readb(rtc->regbase + R64CNT);
+
+               tm->tm_sec      = BCD2BIN(readb(rtc->regbase + RSECCNT));
+               tm->tm_min      = BCD2BIN(readb(rtc->regbase + RMINCNT));
+               tm->tm_hour     = BCD2BIN(readb(rtc->regbase + RHRCNT));
+               tm->tm_wday     = BCD2BIN(readb(rtc->regbase + RWKCNT));
+               tm->tm_mday     = BCD2BIN(readb(rtc->regbase + RDAYCNT));
+               tm->tm_mon      = BCD2BIN(readb(rtc->regbase + RMONCNT));
+
+#if defined(CONFIG_CPU_SH4)
+               yr  = readw(rtc->regbase + RYRCNT);
+               yr100 = BCD2BIN(yr >> 8);
+               yr &= 0xff;
+#else
+               yr  = readb(rtc->regbase + RYRCNT);
+               yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20);
+#endif
+
+               tm->tm_year = (yr100 * 100 + BCD2BIN(yr)) - 1900;
+
+               sec2 = readb(rtc->regbase + R64CNT);
+               cf_bit = readb(rtc->regbase + RCR1) & RCR1_CF;
+
+               spin_unlock_irq(&rtc->lock);
+       } while (cf_bit != 0 || ((sec128 ^ sec2) & RTC_BIT_INVERTED) != 0);
+
+#if RTC_BIT_INVERTED != 0
+       if ((sec128 & RTC_BIT_INVERTED))
+               tm->tm_sec--;
+#endif
+
+       dev_dbg(&dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+               "mday=%d, mon=%d, year=%d, wday=%d\n",
+               __FUNCTION__,
+               tm->tm_sec, tm->tm_min, tm->tm_hour,
+               tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+       if (rtc_valid_tm(tm) < 0)
+               dev_err(dev, "invalid date\n");
+
+       return 0;
+}
+
+static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct sh_rtc *rtc = platform_get_drvdata(pdev);
+       unsigned int tmp;
+       int year;
+
+       spin_lock_irq(&rtc->lock);
+
+       /* Reset pre-scaler & stop RTC */
+       tmp = readb(rtc->regbase + RCR2);
+       tmp |= RCR2_RESET;
+       writeb(tmp, rtc->regbase + RCR2);
+
+       writeb(BIN2BCD(tm->tm_sec),  rtc->regbase + RSECCNT);
+       writeb(BIN2BCD(tm->tm_min),  rtc->regbase + RMINCNT);
+       writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT);
+       writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT);
+       writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT);
+       writeb(BIN2BCD(tm->tm_mon),  rtc->regbase + RMONCNT);
+
+#ifdef CONFIG_CPU_SH3
+       year = tm->tm_year % 100;
+       writeb(BIN2BCD(year), rtc->regbase + RYRCNT);
+#else
+       year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) |
+               BIN2BCD(tm->tm_year % 100);
+       writew(year, rtc->regbase + RYRCNT);
+#endif
+
+       /* Start RTC */
+       tmp = readb(rtc->regbase + RCR2);
+       tmp &= ~RCR2_RESET;
+       tmp |= RCR2_RTCEN | RCR2_START;
+       writeb(tmp, rtc->regbase + RCR2);
+
+       spin_unlock_irq(&rtc->lock);
+
+       return 0;
+}
+
+static struct rtc_class_ops sh_rtc_ops = {
+       .open           = sh_rtc_open,
+       .release        = sh_rtc_release,
+       .ioctl          = sh_rtc_ioctl,
+       .read_time      = sh_rtc_read_time,
+       .set_time       = sh_rtc_set_time,
+       .proc           = sh_rtc_proc,
+};
+
+static int __devinit sh_rtc_probe(struct platform_device *pdev)
+{
+       struct sh_rtc *rtc;
+       struct resource *res;
+       int ret = -ENOENT;
+
+       rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
+       if (unlikely(!rtc))
+               return -ENOMEM;
+
+       spin_lock_init(&rtc->lock);
+
+       rtc->periodic_irq = platform_get_irq(pdev, 0);
+       if (unlikely(rtc->periodic_irq < 0)) {
+               dev_err(&pdev->dev, "No IRQ for period\n");
+               goto err_badres;
+       }
+
+       rtc->carry_irq = platform_get_irq(pdev, 1);
+       if (unlikely(rtc->carry_irq < 0)) {
+               dev_err(&pdev->dev, "No IRQ for carry\n");
+               goto err_badres;
+       }
+
+       rtc->alarm_irq = platform_get_irq(pdev, 2);
+       if (unlikely(rtc->alarm_irq < 0)) {
+               dev_err(&pdev->dev, "No IRQ for alarm\n");
+               goto err_badres;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (unlikely(res == NULL)) {
+               dev_err(&pdev->dev, "No IO resource\n");
+               goto err_badres;
+       }
+
+       rtc->regsize = res->end - res->start + 1;
+
+       rtc->res = request_mem_region(res->start, rtc->regsize, pdev->name);
+       if (unlikely(!rtc->res)) {
+               ret = -EBUSY;
+               goto err_badres;
+       }
+
+       rtc->regbase = (void __iomem *)rtc->res->start;
+       if (unlikely(!rtc->regbase)) {
+               ret = -EINVAL;
+               goto err_badmap;
+       }
+
+       rtc->rtc_dev = rtc_device_register("sh", &pdev->dev,
+                                          &sh_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc)) {
+               ret = PTR_ERR(rtc->rtc_dev);
+               goto err_badmap;
+       }
+
+       platform_set_drvdata(pdev, rtc);
+
+       return 0;
+
+err_badmap:
+       release_resource(rtc->res);
+err_badres:
+       kfree(rtc);
+
+       return ret;
+}
+
+static int __devexit sh_rtc_remove(struct platform_device *pdev)
+{
+       struct sh_rtc *rtc = platform_get_drvdata(pdev);
+
+       if (likely(rtc->rtc_dev))
+               rtc_device_unregister(rtc->rtc_dev);
+
+       sh_rtc_setpie(&pdev->dev, 0);
+       sh_rtc_setaie(&pdev->dev, 0);
+
+       release_resource(rtc->res);
+
+       platform_set_drvdata(pdev, NULL);
+
+       kfree(rtc);
+
+       return 0;
+}
+static struct platform_driver sh_rtc_platform_driver = {
+       .driver         = {
+               .name   = "sh-rtc",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = sh_rtc_probe,
+       .remove         = __devexit_p(sh_rtc_remove),
+};
+
+static int __init sh_rtc_init(void)
+{
+       return platform_driver_register(&sh_rtc_platform_driver);
+}
+
+static void __exit sh_rtc_exit(void)
+{
+       platform_driver_unregister(&sh_rtc_platform_driver);
+}
+
+module_init(sh_rtc_init);
+module_exit(sh_rtc_exit);
+
+MODULE_DESCRIPTION("SuperH on-chip RTC driver");
+MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
+MODULE_LICENSE("GPL");
index 0e4a7ebe300a07d1bb51686cbc804436b639ae2f..6b35ed8301e0dac3211968409505bc2f4f63fbb2 100644 (file)
@@ -681,6 +681,7 @@ static struct eisa_device_id aha1740_ids[] = {
        { "ADP0400" },          /* 1744  */
        { "" }
 };
+MODULE_DEVICE_TABLE(eisa, aha1740_ids);
 
 static struct eisa_driver aha1740_driver = {
        .id_table = aha1740_ids,
index 867cbe23579b6310f583187c4b927494f4edb54b..1ac119733bac3b2ceef4fea3a228931037366664 100644 (file)
@@ -132,7 +132,8 @@ static struct eisa_device_id aic7770_ids[] = {
        { "ADP7770", 5 }, /* AIC7770 generic */
        { "" }
 };
-  
+MODULE_DEVICE_TABLE(eisa, aic7770_ids);
+
 static struct eisa_driver aic7770_driver = {
        .id_table       = aic7770_ids,
        .driver = {
index 592b52afe6582ceed90c1870617b061b6d3a2e24..683fc7ae4b8ffb1f52823779d81b852db3fb2274 100644 (file)
@@ -1756,16 +1756,23 @@ static void set_mesh_power(struct mesh_state *ms, int state)
                pmac_call_feature(PMAC_FTR_MESH_ENABLE, macio_get_of_node(ms->mdev), 0, 0);
                msleep(10);
        }
-}                      
+}
 
 
 #ifdef CONFIG_PM
-static int mesh_suspend(struct macio_dev *mdev, pm_message_t state)
+static int mesh_suspend(struct macio_dev *mdev, pm_message_t mesg)
 {
        struct mesh_state *ms = (struct mesh_state *)macio_get_drvdata(mdev);
        unsigned long flags;
 
-       if (state.event == mdev->ofdev.dev.power.power_state.event || state.event < 2)
+       switch (mesg.event) {
+       case PM_EVENT_SUSPEND:
+       case PM_EVENT_FREEZE:
+               break;
+       default:
+               return 0;
+       }
+       if (mesg.event == mdev->ofdev.dev.power.power_state.event)
                return 0;
 
        scsi_block_requests(ms->host);
@@ -1780,7 +1787,7 @@ static int mesh_suspend(struct macio_dev *mdev, pm_message_t state)
        disable_irq(ms->meshintr);
        set_mesh_power(ms, 0);
 
-       mdev->ofdev.dev.power.power_state = state;
+       mdev->ofdev.dev.power.power_state = mesg;
 
        return 0;
 }
index b27e85428daab7a59decef0a2ba3e170afb0bca2..551baccec5230c57ec2fb3bcdf714d7969fe1fab 100644 (file)
@@ -282,6 +282,7 @@ static struct eisa_device_id sim710_eisa_ids[] = {
        { "HWP0C80" },
        { "" }
 };
+MODULE_DEVICE_TABLE(eisa, sim710_eisa_ids);
 
 static __init int
 sim710_eisa_probe(struct device *dev)
index 5b48ac22c9c5964b62b93500831f1656a1b84e1a..261eaa4429532cd9303a7dcf5cbfe0bda9985a65 100644 (file)
@@ -642,12 +642,17 @@ config V850E_UART_CONSOLE
        select SERIAL_CORE_CONSOLE
 
 config SERIAL_SH_SCI
-       tristate "SH SCI(F) serial port support"
+       tristate "SuperH SCI(F) serial port support"
        depends on SUPERH || H8300
        select SERIAL_CORE
 
+config SERIAL_SH_SCI_NR_UARTS
+       int "Maximum number of SCI(F) serial ports"
+       depends on SERIAL_SH_SCI
+       default "2"
+
 config SERIAL_SH_SCI_CONSOLE
-       bool "Support for console on SH SCI(F)"
+       bool "Support for console on SuperH SCI(F)"
        depends on SERIAL_SH_SCI=y
        select SERIAL_CORE_CONSOLE
 
index cbede06cac27915d92664b1019b5a859adfdbb62..f336ba6778dd6bdbbffe4fd2a9f37a930021544d 100644 (file)
@@ -3,7 +3,7 @@
  *
  * SuperH on-chip serial module support.  (SCI with no FIFO / with FIFO)
  *
- *  Copyright (C) 2002, 2003, 2004  Paul Mundt
+ *  Copyright (C) 2002 - 2006  Paul Mundt
  *
  * based off of the old drivers/char/sh-sci.c by:
  *
 
 #undef DEBUG
 
+#include <linux/config.h>
 #include <linux/module.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>
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/sysrq.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/console.h>
-#include <linux/bitops.h>
-#include <linux/generic_serial.h>
+#include <linux/platform_device.h>
 
 #ifdef CONFIG_CPU_FREQ
 #include <linux/notifier.h>
 #include <linux/cpufreq.h>
 #endif
 
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
 #if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
 #include <asm/clock.h>
-#endif
-
-#ifdef CONFIG_SH_STANDARD_BIOS
 #include <asm/sh_bios.h>
+#include <asm/kgdb.h>
 #endif
 
+#include <asm/sci.h>
+
 #if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 #endif
 
 #include "sh-sci.h"
 
-#ifdef CONFIG_SH_KGDB
-#include <asm/kgdb.h>
+struct sci_port {
+       struct uart_port        port;
+
+       /* Port type */
+       unsigned int            type;
+
+       /* Port IRQs: ERI, RXI, TXI, BRI (optional) */
+       unsigned int            irqs[SCIx_NR_IRQS]; 
+
+       /* Port pin configuration */
+       void                    (*init_pins)(struct uart_port *port,
+                                            unsigned int cflag);
 
-static int kgdb_get_char(struct sci_port *port);
-static void kgdb_put_char(struct sci_port *port, char c);
-static void kgdb_handle_error(struct sci_port *port);
+       /* Port enable callback */
+       void                    (*enable)(struct uart_port *port);
+
+       /* Port disable callback */
+       void                    (*disable)(struct uart_port *port);
+
+       /* Break timer */
+       struct timer_list       break_timer;
+       int                     break_flag;
+};
+
+#ifdef CONFIG_SH_KGDB
 static struct sci_port *kgdb_sci_port;
-#endif /* CONFIG_SH_KGDB */
+#endif
 
 #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
-static struct sci_port *serial_console_port = 0;
-#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
+static struct sci_port *serial_console_port;
+#endif
 
 /* Function prototypes */
 static void sci_stop_tx(struct uart_port *port);
-static void sci_start_tx(struct uart_port *port);
-static void sci_start_rx(struct uart_port *port, unsigned int tty_start);
-static void sci_stop_rx(struct uart_port *port);
-static int sci_request_irq(struct sci_port *port);
-static void sci_free_irq(struct sci_port *port);
-
-static struct sci_port sci_ports[];
-static struct uart_driver sci_uart_driver;
 
-#define SCI_NPORTS sci_uart_driver.nr
+#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
 
-#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+static struct sci_port sci_ports[SCI_NPORTS];
+static struct uart_driver sci_uart_driver;
 
-static void handle_error(struct uart_port *port)
-{                              /* Clear error flags */
+#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) && \
+    defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
+static inline void handle_error(struct uart_port *port)
+{
+       /* Clear error flags */
        sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
 }
 
@@ -106,8 +111,8 @@ static int get_char(struct uart_port *port)
        unsigned short status;
        int c;
 
-       local_irq_save(flags);
-        do {
+       spin_lock_irqsave(&port->lock, flags);
+       do {
                status = sci_in(port, SCxSR);
                if (status & SCxSR_ERRORS(port)) {
                        handle_error(port);
@@ -117,38 +122,19 @@ static int get_char(struct uart_port *port)
        c = sci_in(port, SCxRDR);
        sci_in(port, SCxSR);            /* Dummy read */
        sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
-       local_irq_restore(flags);
+       spin_unlock_irqrestore(&port->lock, flags);
 
        return c;
 }
-
-/* Taken from sh-stub.c of GDB 4.18 */
-static const char hexchars[] = "0123456789abcdef";
-
-static __inline__ char highhex(int  x)
-{
-       return hexchars[(x >> 4) & 0xf];
-}
-
-static __inline__ char lowhex(int  x)
-{
-       return hexchars[x & 0xf];
-}
-
 #endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
 
-/*
- * Send the packet in buffer.  The host gets one chance to read it.
- * This routine does not wait for a positive acknowledge.
- */
-
-#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
+#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) || defined(CONFIG_SH_KGDB)
 static void put_char(struct uart_port *port, char c)
 {
        unsigned long flags;
        unsigned short status;
 
-       local_irq_save(flags);
+       spin_lock_irqsave(&port->lock, flags);
 
        do {
                status = sci_in(port, SCxSR);
@@ -158,9 +144,11 @@ static void put_char(struct uart_port *port, char c)
        sci_in(port, SCxSR);            /* Dummy read */
        sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
 
-       local_irq_restore(flags);
+       spin_unlock_irqrestore(&port->lock, flags);
 }
+#endif
 
+#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
 static void put_string(struct sci_port *sci_port, const char *buffer, int count)
 {
        struct uart_port *port = &sci_port->port;
@@ -213,96 +201,28 @@ static void put_string(struct sci_port *sci_port, const char *buffer, int count)
 }
 #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
 
-
 #ifdef CONFIG_SH_KGDB
-
-/* Is the SCI ready, ie is there a char waiting? */
-static int kgdb_is_char_ready(struct sci_port *port)
-{
-        unsigned short status = sci_in(port, SCxSR);
-
-        if (status & (SCxSR_ERRORS(port) | SCxSR_BRK(port)))
-                kgdb_handle_error(port);
-
-        return (status & SCxSR_RDxF(port));
-}
-
-/* Write a char */
-static void kgdb_put_char(struct sci_port *port, char c)
-{
-        unsigned short status;
-
-        do
-                status = sci_in(port, SCxSR);
-        while (!(status & SCxSR_TDxE(port)));
-
-        sci_out(port, SCxTDR, c);
-        sci_in(port, SCxSR);    /* Dummy read */
-        sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port));
-}
-
-/* Get a char if there is one, else ret -1 */
-static int kgdb_get_char(struct sci_port *port)
-{
-        int c;
-
-        if (kgdb_is_char_ready(port) == 0)
-                c = -1;
-        else {
-                c = sci_in(port, SCxRDR);
-                sci_in(port, SCxSR);    /* Dummy read */
-                sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
-        }
-
-        return c;
-}
-
-/* Called from kgdbstub.c to get a character, i.e. is blocking */
 static int kgdb_sci_getchar(void)
 {
-        volatile int c;
+        int c;
 
         /* Keep trying to read a character, this could be neater */
-        while ((c = kgdb_get_char(kgdb_sci_port)) < 0);
+        while ((c = get_char(kgdb_sci_port)) < 0)
+               cpu_relax();
 
         return c;
 }
 
-/* Called from kgdbstub.c to put a character, just a wrapper */
-static void kgdb_sci_putchar(int c)
-{
-
-        kgdb_put_char(kgdb_sci_port, c);
-}
-
-/* Clear any errors on the SCI */
-static void kgdb_handle_error(struct sci_port *port)
+static inline void kgdb_sci_putchar(int c)
 {
-        sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));  /* Clear error flags */
+        put_char(kgdb_sci_port, c);
 }
-
-/* Breakpoint if there's a break sent on the serial port */
-static void kgdb_break_interrupt(int irq, void *ptr, struct pt_regs *regs)
-{
-        struct sci_port *port = ptr;
-        unsigned short status = sci_in(port, SCxSR);
-
-        if (status & SCxSR_BRK(port)) {
-
-                /* Break into the debugger if a break is detected */
-                BREAKPOINT();
-
-                /* Clear */
-                sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
-        }
-}
-
 #endif /* CONFIG_SH_KGDB */
 
 #if defined(__H8300S__)
 enum { sci_disable, sci_enable };
 
-static void h8300_sci_enable(struct uart_port* port, unsigned int ctrl)
+static void h8300_sci_config(struct uart_port* port, unsigned int ctrl)
 {
        volatile unsigned char *mstpcrl=(volatile unsigned char *)MSTPCRL;
        int ch = (port->mapbase  - SMR0) >> 3;
@@ -314,32 +234,66 @@ static void h8300_sci_enable(struct uart_port* port, unsigned int ctrl)
                *mstpcrl &= ~mask;
        }
 }
+
+static inline void h8300_sci_enable(struct uart_port *port)
+{
+       h8300_sci_config(port, sci_enable);
+}
+
+static inline void h8300_sci_disable(struct uart_port *port)
+{
+       h8300_sci_config(port, sci_disable);
+}
 #endif
 
-#if defined(SCI_ONLY) || defined(SCI_AND_SCIF)
-#if defined(__H8300H__) || defined(__H8300S__)
+#if defined(SCI_ONLY) || defined(SCI_AND_SCIF) && \
+    defined(__H8300H__) || defined(__H8300S__)
 static void sci_init_pins_sci(struct uart_port* port, unsigned int cflag)
 {
        int ch = (port->mapbase - SMR0) >> 3;
 
        /* set DDR regs */
-       H8300_GPIO_DDR(h8300_sci_pins[ch].port,h8300_sci_pins[ch].rx,H8300_GPIO_INPUT);
-       H8300_GPIO_DDR(h8300_sci_pins[ch].port,h8300_sci_pins[ch].tx,H8300_GPIO_OUTPUT);
+       H8300_GPIO_DDR(h8300_sci_pins[ch].port,
+                      h8300_sci_pins[ch].rx,
+                      H8300_GPIO_INPUT);
+       H8300_GPIO_DDR(h8300_sci_pins[ch].port,
+                      h8300_sci_pins[ch].tx,
+                      H8300_GPIO_OUTPUT);
+
        /* tx mark output*/
        H8300_SCI_DR(ch) |= h8300_sci_pins[ch].tx;
 }
+#else
+#define sci_init_pins_sci NULL
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag)
+{
+       unsigned int fcr_val = 0;
+
+       if (cflag & CRTSCTS)
+               fcr_val |= SCFCR_MCE;
+
+       sci_out(port, SCFCR, fcr_val);
+}
+#else
+#define sci_init_pins_irda NULL
 #endif
+
+#ifdef SCI_ONLY
+#define sci_init_pins_scif NULL
 #endif
 
 #if defined(SCIF_ONLY) || defined(SCI_AND_SCIF)
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7710)
 /* SH7300 doesn't use RTS/CTS */
 static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 {
        sci_out(port, SCFCR, 0);
 }
 #elif defined(CONFIG_CPU_SH3)
-/* For SH7705, SH7707, SH7709, SH7709A, SH7729 */
+/* For SH7705, SH7706, SH7707, SH7709, SH7709A, SH7729 */
 static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 {
        unsigned int fcr_val = 0;
@@ -366,20 +320,7 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 
        sci_out(port, SCFCR, fcr_val);
 }
-
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
-static void sci_init_pins_irda(struct uart_port *port, unsigned int cflag)
-{
-       unsigned int fcr_val = 0;
-
-       if (cflag & CRTSCTS)
-               fcr_val |= SCFCR_MCE;
-
-       sci_out(port, SCFCR, fcr_val);
-}
-#endif
 #else
-
 /* For SH7750 */
 static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 {
@@ -388,7 +329,9 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
        if (cflag & CRTSCTS) {
                fcr_val |= SCFCR_MCE;
        } else {
-#ifdef CONFIG_CPU_SUBTYPE_SH7780
+#ifdef CONFIG_CPU_SUBTYPE_SH7343
+               /* Nothing */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
                ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */
 #else
                ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */
@@ -396,10 +339,41 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
        }
        sci_out(port, SCFCR, fcr_val);
 }
+#endif
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
+static inline int scif_txroom(struct uart_port *port)
+{
+       return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0x7f);
+}
+
+static inline int scif_rxroom(struct uart_port *port)
+{
+       return sci_in(port, SCRFDR) & 0x7f;
+}
+#else
+static inline int scif_txroom(struct uart_port *port)
+{
+       return SCIF_TXROOM_MAX - (sci_in(port, SCFDR) >> 8);
+}
 
+static inline int scif_rxroom(struct uart_port *port)
+{
+       return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
+}
 #endif
 #endif /* SCIF_ONLY || SCI_AND_SCIF */
 
+static inline int sci_txroom(struct uart_port *port)
+{
+       return ((sci_in(port, SCxSR) & SCI_TDRE) != 0);
+}
+
+static inline int sci_rxroom(struct uart_port *port)
+{
+       return ((sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0);
+}
+
 /* ********************************************************************** *
  *                   the interrupt related routines                       *
  * ********************************************************************** */
@@ -408,14 +382,12 @@ static void sci_transmit_chars(struct uart_port *port)
 {
        struct circ_buf *xmit = &port->info->xmit;
        unsigned int stopped = uart_tx_stopped(port);
-       unsigned long flags;
        unsigned short status;
        unsigned short ctrl;
-       int count, txroom;
+       int count;
 
        status = sci_in(port, SCxSR);
        if (!(status & SCxSR_TDxE(port))) {
-               local_irq_save(flags);
                ctrl = sci_in(port, SCSCR);
                if (uart_circ_empty(xmit)) {
                        ctrl &= ~SCI_CTRL_FLAGS_TIE;
@@ -423,25 +395,15 @@ static void sci_transmit_chars(struct uart_port *port)
                        ctrl |= SCI_CTRL_FLAGS_TIE;
                }
                sci_out(port, SCSCR, ctrl);
-               local_irq_restore(flags);
                return;
        }
 
-#if !defined(SCI_ONLY)
-       if (port->type == PORT_SCIF) {
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
-               txroom = SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0x7f);
-#else
-               txroom = SCIF_TXROOM_MAX - (sci_in(port, SCFDR)>>8);
-#endif
-       } else {
-               txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0;
-       }
-#else
-       txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0;
+#ifndef SCI_ONLY
+       if (port->type == PORT_SCIF)
+               count = scif_txroom(port);
+       else
 #endif
-
-       count = txroom;
+               count = sci_txroom(port);
 
        do {
                unsigned char c;
@@ -468,7 +430,6 @@ static void sci_transmit_chars(struct uart_port *port)
        if (uart_circ_empty(xmit)) {
                sci_stop_tx(port);
        } else {
-               local_irq_save(flags);
                ctrl = sci_in(port, SCSCR);
 
 #if !defined(SCI_ONLY)
@@ -480,7 +441,6 @@ static void sci_transmit_chars(struct uart_port *port)
 
                ctrl |= SCI_CTRL_FLAGS_TIE;
                sci_out(port, SCSCR, ctrl);
-               local_irq_restore(flags);
        }
 }
 
@@ -490,6 +450,7 @@ static void sci_transmit_chars(struct uart_port *port)
 static inline void sci_receive_chars(struct uart_port *port,
                                     struct pt_regs *regs)
 {
+       struct sci_port *sci_port = (struct sci_port *)port;
        struct tty_struct *tty = port->info->tty;
        int i, count, copied = 0;
        unsigned short status;
@@ -501,18 +462,11 @@ static inline void sci_receive_chars(struct uart_port *port,
 
        while (1) {
 #if !defined(SCI_ONLY)
-               if (port->type == PORT_SCIF) {
-#if defined(CONFIG_CPU_SUBTYPE_SH7760) || defined(CONFIG_CPU_SUBTYPE_SH7780)
-                       count = sci_in(port, SCRFDR) & 0x7f;
-#else
-                       count = sci_in(port, SCFDR)&SCIF_RFDC_MASK ;
-#endif
-               } else {
-                       count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0;
-               }
-#else
-               count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0;
+               if (port->type == PORT_SCIF)
+                       count = scif_rxroom(port);
+               else
 #endif
+                       count = sci_rxroom(port);
 
                /* Don't copy more bytes than there is room for in the buffer */
                count = tty_buffer_request_room(tty, count);
@@ -523,11 +477,10 @@ static inline void sci_receive_chars(struct uart_port *port,
 
                if (port->type == PORT_SCI) {
                        char c = sci_in(port, SCxRDR);
-                       if(((struct sci_port *)port)->break_flag
-                           || uart_handle_sysrq_char(port, c, regs)) {
+                       if (uart_handle_sysrq_char(port, c, regs) || sci_port->break_flag)
                                count = 0;
-                       else {
-                           tty_insert_flip_char(tty, c, TTY_NORMAL);
+                       else {
+                               tty_insert_flip_char(tty, c, TTY_NORMAL);
                        }
                } else {
                        for (i=0; i<count; i++) {
@@ -535,15 +488,17 @@ static inline void sci_receive_chars(struct uart_port *port,
                                status = sci_in(port, SCxSR);
 #if defined(CONFIG_CPU_SH3)
                                /* Skip "chars" during break */
-                               if (((struct sci_port *)port)->break_flag) {
+                               if (sci_port->break_flag) {
                                        if ((c == 0) &&
                                            (status & SCxSR_FER(port))) {
                                                count--; i--;
                                                continue;
                                        }
+
                                        /* Nonzero => end-of-break */
                                        pr_debug("scif: debounce<%02x>\n", c);
-                                       ((struct sci_port *)port)->break_flag = 0;
+                                       sci_port->break_flag = 0;
+
                                        if (STEPFN(c)) {
                                                count--; i--;
                                                continue;
@@ -600,15 +555,17 @@ static void sci_schedule_break_timer(struct sci_port *port)
 /* Ensure that two consecutive samples find the break over. */
 static void sci_break_timer(unsigned long data)
 {
-    struct sci_port * port = (struct sci_port *)data;
-       if(sci_rxd_in(&port->port) == 0) {
+       struct sci_port *port = (struct sci_port *)data;
+
+       if (sci_rxd_in(&port->port) == 0) {
                port->break_flag = 1;
-           sci_schedule_break_timer(port);
-       } else if(port->break_flag == 1){
+               sci_schedule_break_timer(port);
+       } else if (port->break_flag == 1) {
                /* break is over. */
                port->break_flag = 2;
-           sci_schedule_break_timer(port);
-       } else port->break_flag = 0;
+               sci_schedule_break_timer(port);
+       } else
+               port->break_flag = 0;
 }
 
 static inline int sci_handle_errors(struct uart_port *port)
@@ -617,40 +574,41 @@ static inline int sci_handle_errors(struct uart_port *port)
        unsigned short status = sci_in(port, SCxSR);
        struct tty_struct *tty = port->info->tty;
 
-       if (status&SCxSR_ORER(port)) {
+       if (status & SCxSR_ORER(port)) {
                /* overrun error */
-               if(tty_insert_flip_char(tty, 0, TTY_OVERRUN))
+               if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
                        copied++;
                pr_debug("sci: overrun error\n");
        }
 
-       if (status&SCxSR_FER(port)) {
+       if (status & SCxSR_FER(port)) {
                if (sci_rxd_in(port) == 0) {
                        /* Notify of BREAK */
-                       struct sci_port * sci_port = (struct sci_port *)port;
-                       if(!sci_port->break_flag) {
-                               sci_port->break_flag = 1;
-                               sci_schedule_break_timer((struct sci_port *)port);
+                       struct sci_port *sci_port = (struct sci_port *)port;
+
+                       if (!sci_port->break_flag) {
+                               sci_port->break_flag = 1;
+                               sci_schedule_break_timer(sci_port);
+
                                /* Do sysrq handling. */
-                               if(uart_handle_break(port))
+                               if (uart_handle_break(port))
                                        return 0;
                                pr_debug("sci: BREAK detected\n");
-                               if(tty_insert_flip_char(tty, 0, TTY_BREAK))
+                               if (tty_insert_flip_char(tty, 0, TTY_BREAK))
                                        copied++;
                        }
-               }
-               else {
+               } else {
                        /* frame error */
-                       if(tty_insert_flip_char(tty, 0, TTY_FRAME))
+                       if (tty_insert_flip_char(tty, 0, TTY_FRAME))
                                copied++;
                        pr_debug("sci: frame error\n");
                }
        }
 
-       if (status&SCxSR_PER(port)) {
-               if(tty_insert_flip_char(tty, 0, TTY_PARITY))
-                       copied++;
+       if (status & SCxSR_PER(port)) {
                /* parity error */
+               if (tty_insert_flip_char(tty, 0, TTY_PARITY))
+                       copied++;
                pr_debug("sci: parity error\n");
        }
 
@@ -673,7 +631,7 @@ static inline int sci_handle_breaks(struct uart_port *port)
                s->break_flag = 1;
 #endif
                /* Notify of BREAK */
-               if(tty_insert_flip_char(tty, 0, TTY_BREAK))
+               if (tty_insert_flip_char(tty, 0, TTY_BREAK))
                        copied++;
                pr_debug("sci: BREAK detected\n");
        }
@@ -682,7 +640,7 @@ static inline int sci_handle_breaks(struct uart_port *port)
        /* XXX: Handle SCIF overrun error */
        if (port->type == PORT_SCIF && (sci_in(port, SCLSR) & SCIF_ORER) != 0) {
                sci_out(port, SCLSR, 0);
-               if(tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
+               if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) {
                        copied++;
                        pr_debug("sci: overrun error\n");
                }
@@ -691,13 +649,12 @@ static inline int sci_handle_breaks(struct uart_port *port)
 
        if (copied)
                tty_flip_buffer_push(tty);
+
        return copied;
 }
 
-static irqreturn_t sci_rx_interrupt(int irq, void *ptr, struct pt_regs *regs)
+static irqreturn_t sci_rx_interrupt(int irq, void *port, struct pt_regs *regs)
 {
-       struct uart_port *port = ptr;
-
        /* I think sci_receive_chars has to be called irrespective
         * of whether the I_IXOFF is set, otherwise, how is the interrupt
         * to be disabled?
@@ -711,7 +668,9 @@ static irqreturn_t sci_tx_interrupt(int irq, void *ptr, struct pt_regs *regs)
 {
        struct uart_port *port = ptr;
 
+       spin_lock_irq(&port->lock);
        sci_transmit_chars(port);
+       spin_unlock_irq(&port->lock);
 
        return IRQ_HANDLED;
 }
@@ -755,6 +714,12 @@ static irqreturn_t sci_br_interrupt(int irq, void *ptr, struct pt_regs *regs)
 
        /* Handle BREAKs */
        sci_handle_breaks(port);
+
+#ifdef CONFIG_SH_KGDB
+       /* Break into the debugger if a break is detected */
+       BREAKPOINT();
+#endif
+
        sci_out(port, SCxSR, SCxSR_BREAK_CLEAR(port));
 
        return IRQ_HANDLED;
@@ -769,16 +734,16 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr, struct pt_regs *regs)
         scr_status = sci_in(port,SCSCR);
 
        /* Tx Interrupt */
-        if ((ssr_status&0x0020) && (scr_status&0x0080))
+        if ((ssr_status & 0x0020) && (scr_status & 0x0080))
                 sci_tx_interrupt(irq, ptr, regs);
        /* Rx Interrupt */
-        if ((ssr_status&0x0002) && (scr_status&0x0040))
+        if ((ssr_status & 0x0002) && (scr_status & 0x0040))
                 sci_rx_interrupt(irq, ptr, regs);
        /* Error Interrupt */
-        if ((ssr_status&0x0080) && (scr_status&0x0400))
+        if ((ssr_status & 0x0080) && (scr_status & 0x0400))
                 sci_er_interrupt(irq, ptr, regs);
        /* Break Interrupt */
-        if ((ssr_status&0x0010) && (scr_status&0x0200))
+        if ((ssr_status & 0x0010) && (scr_status & 0x0200))
                 sci_br_interrupt(irq, ptr, regs);
 
        return IRQ_HANDLED;
@@ -789,7 +754,8 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr, struct pt_regs *regs)
  * Here we define a transistion notifier so that we can update all of our
  * ports' baud rate when the peripheral clock changes.
  */
-static int sci_notifier(struct notifier_block *self, unsigned long phase, void *p)
+static int sci_notifier(struct notifier_block *self,
+                       unsigned long phase, void *p)
 {
        struct cpufreq_freqs *freqs = p;
        int i;
@@ -816,8 +782,9 @@ static int sci_notifier(struct notifier_block *self, unsigned long phase, void *
                        clk_put(clk);
                }
 
-               printk("%s: got a postchange notification for cpu %d (old %d, new %d)\n",
-                               __FUNCTION__, freqs->cpu, freqs->old, freqs->new);
+               printk(KERN_INFO "%s: got a postchange notification "
+                      "for cpu %d (old %d, new %d)\n",
+                      __FUNCTION__, freqs->cpu, freqs->old, freqs->new);
        }
 
        return NOTIFY_OK;
@@ -841,8 +808,9 @@ static int sci_request_irq(struct sci_port *port)
                        printk(KERN_ERR "sci: Cannot allocate irq.(IRQ=0)\n");
                        return -ENODEV;
                }
-               if (request_irq(port->irqs[0], sci_mpxed_interrupt, IRQF_DISABLED,
-                               "sci", port)) {
+
+               if (request_irq(port->irqs[0], sci_mpxed_interrupt,
+                               SA_INTERRUPT, "sci", port)) {
                        printk(KERN_ERR "sci: Cannot allocate irq.\n");
                        return -ENODEV;
                }
@@ -850,8 +818,8 @@ static int sci_request_irq(struct sci_port *port)
                for (i = 0; i < ARRAY_SIZE(handlers); i++) {
                        if (!port->irqs[i])
                                continue;
-                       if (request_irq(port->irqs[i], handlers[i], IRQF_DISABLED,
-                                       desc[i], port)) {
+                       if (request_irq(port->irqs[i], handlers[i],
+                                       SA_INTERRUPT, desc[i], port)) {
                                printk(KERN_ERR "sci: Cannot allocate irq.\n");
                                return -ENODEV;
                        }
@@ -903,50 +871,42 @@ static unsigned int sci_get_mctrl(struct uart_port *port)
 
 static void sci_start_tx(struct uart_port *port)
 {
-       struct sci_port *s = &sci_ports[port->line];
+       unsigned short ctrl;
 
-       disable_irq(s->irqs[SCIx_TXI_IRQ]);
-       sci_transmit_chars(port);
-       enable_irq(s->irqs[SCIx_TXI_IRQ]);
+       /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
+       ctrl = sci_in(port, SCSCR);
+       ctrl |= SCI_CTRL_FLAGS_TIE;
+       sci_out(port, SCSCR, ctrl);
 }
 
 static void sci_stop_tx(struct uart_port *port)
 {
-       unsigned long flags;
        unsigned short ctrl;
 
        /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */
-       local_irq_save(flags);
        ctrl = sci_in(port, SCSCR);
        ctrl &= ~SCI_CTRL_FLAGS_TIE;
        sci_out(port, SCSCR, ctrl);
-       local_irq_restore(flags);
 }
 
 static void sci_start_rx(struct uart_port *port, unsigned int tty_start)
 {
-       unsigned long flags;
        unsigned short ctrl;
 
        /* Set RIE (Receive Interrupt Enable) bit in SCSCR */
-       local_irq_save(flags);
        ctrl = sci_in(port, SCSCR);
        ctrl |= SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE;
        sci_out(port, SCSCR, ctrl);
-       local_irq_restore(flags);
 }
 
 static void sci_stop_rx(struct uart_port *port)
 {
-       unsigned long flags;
        unsigned short ctrl;
 
        /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */
-       local_irq_save(flags);
        ctrl = sci_in(port, SCSCR);
        ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE);
        sci_out(port, SCSCR, ctrl);
-       local_irq_restore(flags);
 }
 
 static void sci_enable_ms(struct uart_port *port)
@@ -963,9 +923,8 @@ static int sci_startup(struct uart_port *port)
 {
        struct sci_port *s = &sci_ports[port->line];
 
-#if defined(__H8300S__)
-       h8300_sci_enable(port, sci_enable);
-#endif
+       if (s->enable)
+               s->enable(port);
 
        sci_request_irq(s);
        sci_start_tx(port);
@@ -982,9 +941,8 @@ static void sci_shutdown(struct uart_port *port)
        sci_stop_tx(port);
        sci_free_irq(s);
 
-#if defined(__H8300S__)
-       h8300_sci_enable(port, sci_disable);
-#endif
+       if (s->disable)
+               s->disable(port);
 }
 
 static void sci_set_termios(struct uart_port *port, struct termios *termios,
@@ -997,6 +955,23 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios,
 
        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
 
+       switch (baud) {
+               case 0:
+                       t = -1;
+                       break;
+               default:
+               {
+#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+                       struct clk *clk = clk_get("module_clk");
+                       t = SCBRR_VALUE(baud, clk_get_rate(clk));
+                       clk_put(clk);
+#else
+                       t = SCBRR_VALUE(baud);
+#endif
+               }
+                       break;
+       }
+
        spin_lock_irqsave(&port->lock, flags);
 
        do {
@@ -1006,9 +981,8 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios,
        sci_out(port, SCSCR, 0x00);     /* TE=0, RE=0, CKE1=0 */
 
 #if !defined(SCI_ONLY)
-       if (port->type == PORT_SCIF) {
+       if (port->type == PORT_SCIF)
                sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
-       }
 #endif
 
        smr_val = sci_in(port, SCSMR) & 3;
@@ -1025,23 +999,6 @@ static void sci_set_termios(struct uart_port *port, struct termios *termios,
 
        sci_out(port, SCSMR, smr_val);
 
-       switch (baud) {
-               case 0:
-                       t = -1;
-                       break;
-               default:
-               {
-#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
-                       struct clk *clk = clk_get("module_clk");
-                       t = SCBRR_VALUE(baud, clk_get_rate(clk));
-                       clk_put(clk);
-#else
-                       t = SCBRR_VALUE(baud);
-#endif
-               }
-                       break;
-       }
-
        if (t > 0) {
                if(t >= 256) {
                        sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1);
@@ -1092,11 +1049,23 @@ static void sci_config_port(struct uart_port *port, int flags)
 
        port->type = s->type;
 
+       switch (port->type) {
+       case PORT_SCI:
+               s->init_pins = sci_init_pins_sci;
+               break;
+       case PORT_SCIF:
+               s->init_pins = sci_init_pins_scif;
+               break;
+       case PORT_IRDA:
+               s->init_pins = sci_init_pins_irda;
+               break;
+       }
+
 #if defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
        if (port->mapbase == 0)
                port->mapbase = onchip_remap(SCIF_ADDR_SH5, 1024, "SCIF");
 
-       port->membase = (void *)port->mapbase;
+       port->membase = (void __iomem *)port->mapbase;
 #endif
 }
 
@@ -1132,412 +1101,61 @@ static struct uart_ops sci_uart_ops = {
        .verify_port    = sci_verify_port,
 };
 
-static struct sci_port sci_ports[] = {
-#if defined(CONFIG_CPU_SUBTYPE_SH7708)
-       {
-               .port   = {
-                       .membase        = (void *)0xfffffe80,
-                       .mapbase        = 0xfffffe80,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 25,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCI,
-               .irqs           = SCI_IRQS,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7705)
-       {
-               .port   = {
-                       .membase        = (void *)SCIF0,
-                       .mapbase        = SCIF0,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 55,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH3_IRDA_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)SCIF2,
-                       .mapbase        = SCIF2,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 59,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH3_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       }
-#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
-       {
-               .port   = {
-                       .membase        = (void *)0xfffffe80,
-                       .mapbase        = 0xfffffe80,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 25,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCI,
-               .irqs           = SCI_IRQS,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xa4000150,
-                       .mapbase        = 0xa4000150,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 59,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH3_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xa4000140,
-                       .mapbase        = 0xa4000140,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 55,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 2,
-               },
-               .type           = PORT_IRDA,
-               .irqs           = SH3_IRDA_IRQS,
-               .init_pins      = sci_init_pins_irda,
-       }
-#elif defined(CONFIG_CPU_SUBTYPE_SH7300)
-       {
-               .port   = {
-                       .membase        = (void *)0xA4430000,
-                       .mapbase        = 0xA4430000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 25,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7300_SCIF0_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH73180)
-       {
-               .port   = {
-                       .membase        = (void *)0xffe00000,
-                       .mapbase        = 0xffe00000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 25,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH73180_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
-       {
-               .port   = {
-                       .membase        = (void *)0xffe80000,
-                       .mapbase        = 0xffe80000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 43,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH4_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
-       {
-               .port   = {
-                       .membase        = (void *)0xffe00000,
-                       .mapbase        = 0xffe00000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 25,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCI,
-               .irqs           = SCI_IRQS,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xffe80000,
-                       .mapbase        = 0xffe80000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 43,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH4_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7760)
-       {
-               .port   = {
-                       .membase        = (void *)0xfe600000,
-                       .mapbase        = 0xfe600000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 55,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7760_SCIF0_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xfe610000,
-                       .mapbase        = 0xfe610000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 75,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7760_SCIF1_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xfe620000,
-                       .mapbase        = 0xfe620000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 79,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 2,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7760_SCIF2_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
-       {
-               .port   = {
-                       .membase        = (void *)0xffe00000,
-                       .mapbase        = 0xffe00000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 26,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = STB1_SCIF1_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xffe80000,
-                       .mapbase        = 0xffe80000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 43,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH4_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
-       {
-               .port   = {
-                       .iotype         = UPIO_MEM,
-                       .irq            = 42,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH5_SCIF_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffffb0,
-                       .mapbase        = 0x00ffffb0,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 54,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8300H_SCI_IRQS0,
-               .init_pins      = sci_init_pins_sci,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffffb8,
-                       .mapbase        = 0x00ffffb8,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 58,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8300H_SCI_IRQS1,
-               .init_pins      = sci_init_pins_sci,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffffc0,
-                       .mapbase        = 0x00ffffc0,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 62,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 2,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8300H_SCI_IRQS2,
-               .init_pins      = sci_init_pins_sci,
-       },
-#elif defined(CONFIG_H8S2678)
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffff78,
-                       .mapbase        = 0x00ffff78,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 90,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8S_SCI_IRQS0,
-               .init_pins      = sci_init_pins_sci,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffff80,
-                       .mapbase        = 0x00ffff80,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 94,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8S_SCI_IRQS1,
-               .init_pins      = sci_init_pins_sci,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0x00ffff88,
-                       .mapbase        = 0x00ffff88,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 98,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 2,
-               },
-               .type           = PORT_SCI,
-               .irqs           = H8S_SCI_IRQS2,
-               .init_pins      = sci_init_pins_sci,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
-       {
-               .port   = {
-                       .membase        = (void *)0xff923000,
-                       .mapbase        = 0xff923000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 61,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7770_SCIF0_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xff924000,
-                       .mapbase        = 0xff924000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 62,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7770_SCIF1_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xff925000,
-                       .mapbase        = 0xff925000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 63,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 2,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7770_SCIF2_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
-       {
-               .port   = {
-                       .membase        = (void *)0xffe00000,
-                       .mapbase        = 0xffe00000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 43,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 0,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7780_SCIF0_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
-       {
-               .port   = {
-                       .membase        = (void *)0xffe10000,
-                       .mapbase        = 0xffe10000,
-                       .iotype         = UPIO_MEM,
-                       .irq            = 79,
-                       .ops            = &sci_uart_ops,
-                       .flags          = UPF_BOOT_AUTOCONF,
-                       .line           = 1,
-               },
-               .type           = PORT_SCIF,
-               .irqs           = SH7780_SCIF1_IRQS,
-               .init_pins      = sci_init_pins_scif,
-       },
+static void __init sci_init_ports(void)
+{
+       static int first = 1;
+       int i;
+
+       if (!first)
+               return;
+
+       first = 0;
+
+       for (i = 0; i < SCI_NPORTS; i++) {
+               sci_ports[i].port.ops           = &sci_uart_ops;
+               sci_ports[i].port.iotype        = UPIO_MEM;
+               sci_ports[i].port.line          = i;
+               sci_ports[i].port.fifosize      = 1;
+
+#if defined(__H8300H__) || defined(__H8300S__)
+#ifdef __H8300S__
+               sci_ports[i].enable     = h8300_sci_enable;
+               sci_ports[i].disable    = h8300_sci_disable;
+#endif
+               sci_ports[i].port.uartclk = CONFIG_CPU_CLOCK;
+#elif defined(CONFIG_SUPERH64)
+               sci_ports[i].port.uartclk = current_cpu_data.module_clock * 16;
 #else
-#error "CPU subtype not defined"
+               /*
+                * XXX: We should use a proper SCI/SCIF clock
+                */
+               {
+                       struct clk *clk = clk_get("module_clk");
+                       sci_ports[i].port.uartclk = clk_get_rate(clk) * 16;
+                       clk_put(clk);
+               }
 #endif
-};
+
+               sci_ports[i].break_timer.data = (unsigned long)&sci_ports[i];
+               sci_ports[i].break_timer.function = sci_break_timer;
+
+               init_timer(&sci_ports[i].break_timer);
+       }
+}
+
+int __init early_sci_setup(struct uart_port *port)
+{
+       if (unlikely(port->line > SCI_NPORTS))
+               return -ENODEV;
+
+       sci_init_ports();
+
+       sci_ports[port->line].port.membase      = port->membase;
+       sci_ports[port->line].port.mapbase      = port->mapbase;
+       sci_ports[port->line].port.type         = port->type;
+
+       return 0;
+}
 
 #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
 /*
@@ -1559,34 +1177,38 @@ static int __init serial_console_setup(struct console *co, char *options)
        int flow = 'n';
        int ret;
 
+       /*
+        * 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 >= SCI_NPORTS)
+               co->index = 0;
+
        serial_console_port = &sci_ports[co->index];
        port = &serial_console_port->port;
-       port->type = serial_console_port->type;
-
-#ifdef CONFIG_SUPERH64
-       /* This is especially needed on sh64 to remap the SCIF */
-       sci_config_port(port, 0);
-#endif
 
        /*
-        * We need to set the initial uartclk here, since otherwise it will
-        * only ever be setup at sci_init() time.
+        * Also need to check port->type, we don't actually have any
+        * UPIO_PORT ports, but uart_report_port() handily misreports
+        * it anyways if we don't have a port available by the time this is
+        * called.
         */
-#if defined(__H8300H__) || defined(__H8300S__)
-       port->uartclk = CONFIG_CPU_CLOCK;
+       if (!port->type)
+               return -ENODEV;
+       if (!port->membase || !port->mapbase)
+               return -ENODEV;
+
+       spin_lock_init(&port->lock);
+
+       port->type = serial_console_port->type;
+
+       if (port->flags & UPF_IOREMAP)
+               sci_config_port(port, 0);
+
+       if (serial_console_port->enable)
+               serial_console_port->enable(port);
 
-#if defined(__H8300S__)
-       h8300_sci_enable(port, sci_enable);
-#endif
-#elif defined(CONFIG_SUPERH64)
-       port->uartclk = current_cpu_data.module_clock * 16;
-#else
-       {
-               struct clk *clk = clk_get("module_clk");
-               port->uartclk = clk_get_rate(clk) * 16;
-               clk_put(clk);
-       }
-#endif
        if (options)
                uart_parse_options(options, &baud, &parity, &bits, &flow);
 
@@ -1604,17 +1226,17 @@ static struct console serial_console = {
        .device         = uart_console_device,
        .write          = serial_console_write,
        .setup          = serial_console_setup,
-       .flags          = CON_PRINTBUFFER,
+       .flags          = CON_PRINTBUFFER, 
        .index          = -1,
        .data           = &sci_uart_driver,
 };
 
 static int __init sci_console_init(void)
 {
+       sci_init_ports();
        register_console(&serial_console);
        return 0;
 }
-
 console_initcall(sci_console_init);
 #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
 
@@ -1649,6 +1271,8 @@ int __init kgdb_console_setup(struct console *co, char *options)
        int parity = 'n';
        int flow = 'n';
 
+       spin_lock_init(&port->lock);
+
        if (co->index != kgdb_portnum)
                co->index = kgdb_portnum;
 
@@ -1677,10 +1301,10 @@ static struct console kgdb_console = {
 /* Register the KGDB console so we get messages (d'oh!) */
 static int __init kgdb_console_init(void)
 {
+       sci_init_ports();
        register_console(&kgdb_console);
        return 0;
 }
-
 console_initcall(kgdb_console_init);
 #endif /* CONFIG_SH_KGDB_CONSOLE */
 
@@ -1701,60 +1325,132 @@ static struct uart_driver sci_uart_driver = {
        .dev_name       = "ttySC",
        .major          = SCI_MAJOR,
        .minor          = SCI_MINOR_START,
+       .nr             = SCI_NPORTS,
        .cons           = SCI_CONSOLE,
 };
 
-static int __init sci_init(void)
+/*
+ * Register a set of serial devices attached to a platform device.  The
+ * list is terminated with a zero flags entry, which means we expect
+ * all entries to have at least UPF_BOOT_AUTOCONF set. Platforms that need
+ * remapping (such as sh64) should also set UPF_IOREMAP.
+ */
+static int __devinit sci_probe(struct platform_device *dev)
 {
-       int chan, ret;
+       struct plat_sci_port *p = dev->dev.platform_data;
+       int i;
 
-       printk("%s", banner);
+       for (i = 0; p && p->flags != 0 && i < SCI_NPORTS; p++, i++) {
+               struct sci_port *sciport = &sci_ports[i];
 
-       sci_uart_driver.nr = ARRAY_SIZE(sci_ports);
+               sciport->port.mapbase   = p->mapbase;
 
-       ret = uart_register_driver(&sci_uart_driver);
-       if (ret == 0) {
-               for (chan = 0; chan < SCI_NPORTS; chan++) {
-                       struct sci_port *sciport = &sci_ports[chan];
+               /*
+                * For the simple (and majority of) cases where we don't need
+                * to do any remapping, just cast the cookie directly.
+                */
+               if (p->mapbase && !p->membase && !(p->flags & UPF_IOREMAP))
+                       p->membase = (void __iomem *)p->mapbase;
 
-#if defined(__H8300H__) || defined(__H8300S__)
-                       sciport->port.uartclk = CONFIG_CPU_CLOCK;
-#elif defined(CONFIG_SUPERH64)
-                       sciport->port.uartclk = current_cpu_data.module_clock * 16;
-#else
-                       struct clk *clk = clk_get("module_clk");
-                       sciport->port.uartclk = clk_get_rate(clk) * 16;
-                       clk_put(clk);
-#endif
-                       uart_add_one_port(&sci_uart_driver, &sciport->port);
-                       sciport->break_timer.data = (unsigned long)sciport;
-                       sciport->break_timer.function = sci_break_timer;
-                       init_timer(&sciport->break_timer);
-               }
+               sciport->port.membase   = p->membase;
+
+               sciport->port.irq       = p->irqs[SCIx_TXI_IRQ];
+               sciport->port.flags     = p->flags;
+               sciport->port.dev       = &dev->dev;
+
+               sciport->type           = sciport->port.type = p->type;
+
+               memcpy(&sciport->irqs, &p->irqs, sizeof(p->irqs));
+
+               uart_add_one_port(&sci_uart_driver, &sciport->port);
        }
 
 #ifdef CONFIG_CPU_FREQ
        cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER);
-       printk("sci: CPU frequency notifier registered\n");
+       dev_info(&dev->dev, "sci: CPU frequency notifier registered\n");
 #endif
 
 #ifdef CONFIG_SH_STANDARD_BIOS
        sh_bios_gdb_detach();
 #endif
 
-       return ret;
+       return 0;
 }
 
-static void __exit sci_exit(void)
+static int __devexit sci_remove(struct platform_device *dev)
+{
+       int i;
+
+       for (i = 0; i < SCI_NPORTS; i++)
+               uart_remove_one_port(&sci_uart_driver, &sci_ports[i].port);
+
+       return 0;
+}
+
+static int sci_suspend(struct platform_device *dev, pm_message_t state)
 {
-       int chan;
+       int i;
+
+       for (i = 0; i < SCI_NPORTS; i++) {
+               struct sci_port *p = &sci_ports[i];
+
+               if (p->type != PORT_UNKNOWN && p->port.dev == &dev->dev)
+                       uart_suspend_port(&sci_uart_driver, &p->port);
+       }
 
-       for (chan = 0; chan < SCI_NPORTS; chan++)
-               uart_remove_one_port(&sci_uart_driver, &sci_ports[chan].port);
+       return 0;
+}
 
+static int sci_resume(struct platform_device *dev)
+{
+       int i;
+
+       for (i = 0; i < SCI_NPORTS; i++) {
+               struct sci_port *p = &sci_ports[i];
+
+               if (p->type != PORT_UNKNOWN && p->port.dev == &dev->dev)
+                       uart_resume_port(&sci_uart_driver, &p->port);
+       }
+
+       return 0;
+}
+
+static struct platform_driver sci_driver = {
+       .probe          = sci_probe,
+       .remove         = __devexit_p(sci_remove),
+       .suspend        = sci_suspend,
+       .resume         = sci_resume,
+       .driver         = {
+               .name   = "sh-sci",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init sci_init(void)
+{
+       int ret;
+
+       printk(banner);
+
+       sci_init_ports();
+
+       ret = uart_register_driver(&sci_uart_driver);
+       if (likely(ret == 0)) {
+               ret = platform_driver_register(&sci_driver);
+               if (unlikely(ret))
+                       uart_unregister_driver(&sci_uart_driver);
+       }
+
+       return ret;
+}
+
+static void __exit sci_exit(void)
+{
+       platform_driver_unregister(&sci_driver);
        uart_unregister_driver(&sci_uart_driver);
 }
 
 module_init(sci_init);
 module_exit(sci_exit);
 
+MODULE_LICENSE("GPL");
index ab320fa3237c7f29ac29f6077c802574f70aeaca..28643c4dc850178e15d6d1970682065de6e8e552 100644 (file)
@@ -10,7 +10,9 @@
  *  Modified to support SH7300(SH-Mobile) SCIF. Takashi Kusuda (Jun 2003).
  *  Modified to support H8/300 Series Yoshinori Sato (Feb 2004).
  */
+#include <linux/config.h>
 #include <linux/serial_core.h>
+#include <asm/io.h>
 
 #if defined(__H8300H__) || defined(__H8300S__)
 #include <asm/gpio.h>
 #endif
 #endif
 
-/* Offsets into the sci_port->irqs array */
-#define SCIx_ERI_IRQ 0
-#define SCIx_RXI_IRQ 1
-#define SCIx_TXI_IRQ 2
-
-/*                     ERI, RXI, TXI, BRI */
-#define SCI_IRQS      { 23,  24,  25,   0 }
-#define SH3_SCIF_IRQS { 56,  57,  59,  58 }
-#define SH3_IRDA_IRQS { 52,  53,  55,  54 }
-#define SH4_SCIF_IRQS { 40,  41,  43,  42 }
-#define STB1_SCIF1_IRQS {23, 24,  26,  25 }
-#define SH7760_SCIF0_IRQS { 52, 53, 55, 54 }
-#define SH7760_SCIF1_IRQS { 72, 73, 75, 74 }
-#define SH7760_SCIF2_IRQS { 76, 77, 79, 78 }
-#define SH7300_SCIF0_IRQS {80,  80,  80,  80 }
-#define SH73180_SCIF_IRQS {80,  81,  83,  82 }
-#define H8300H_SCI_IRQS0 {52, 53, 54,   0 }
-#define H8300H_SCI_IRQS1 {56, 57, 58,   0 }
-#define H8300H_SCI_IRQS2 {60, 61, 62,   0 }
-#define H8S_SCI_IRQS0 {88, 89, 90,   0 }
-#define H8S_SCI_IRQS1 {92, 93, 94,   0 }
-#define H8S_SCI_IRQS2 {96, 97, 98,   0 }
-#define SH5_SCIF_IRQS {39, 40, 42,   0 }
-#define        SH7770_SCIF0_IRQS {61, 61, 61, 61 }
-#define        SH7770_SCIF1_IRQS {62, 62, 62, 62 }
-#define        SH7770_SCIF2_IRQS {63, 63, 63, 63 }
-#define        SH7780_SCIF0_IRQS {40, 41, 43, 42 }
-#define        SH7780_SCIF1_IRQS {76, 77, 79, 78 }
-
 #if defined(CONFIG_CPU_SUBTYPE_SH7708)
 # define SCSPTR 0xffffff7c /* 8 bit */
 # define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCI_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7706)
 # define SCPCR  0xA4000116 /* 16 bit SCI and SCIF */
 # define SCPDR  0xA4000136 /* 8  bit SCI and SCIF */
 # define SCSCR_INIT(port)          0x30 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCPDR  0xA4050136        /* 16 bit SCIF */
 # define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710)
+# define SCSPTR0 0xA4400000      /* 16 bit SCIF */
+# define SCSCR_INIT(port)  0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
+# define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH73180)
 # define SCPDR  0xA4050138        /* 16 bit SCIF */
 # define SCSPTR2 SCPDR
 # define SCIF_ORER 0x0001   /* overrun error bit */
 # define SCSCR_INIT(port)  0x0038 /* TIE=0,RIE=0,TE=1,RE=1 */
 # define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
+# define SCSPTR0 0xffe00010    /* 16 bit SCIF */
+# define SCSPTR1 0xffe10010    /* 16 bit SCIF */
+# define SCSPTR2 0xffe20010    /* 16 bit SCIF */
+# define SCSPTR3 0xffe30010    /* 16 bit SCIF */
+# define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */
+# define SCIF_ONLY
 #elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
 # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 # define SCSPTR0       0xffe00024      /* 16 bit SCIF */
 # define SCSPTR1       0xffe10024      /* 16 bit SCIF */
-# define SCIF_OPER     0x0001          /* Overrun error bit */
+# define SCIF_ORER     0x0001          /* Overrun error bit */
 # define SCSCR_INIT(port)      0x3a    /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
 # define SCIF_ONLY
 #else
  */
 #define SCI_EVENT_WRITE_WAKEUP 0
 
-struct sci_port {
-       struct uart_port port;
-       int type;
-       unsigned char irqs[4]; /* ERI, RXI, TXI, BRI */
-       void (*init_pins)(struct uart_port *port, unsigned int cflag);
-       int break_flag;
-       struct timer_list break_timer;
-};
-
 #define SCI_IN(size, offset)                                   \
   unsigned int addr = port->mapbase + (offset);                        \
   if ((size) == 8) {                                           \
@@ -336,7 +313,9 @@ struct sci_port {
   }
 
 #ifdef CONFIG_CPU_SH3
-#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7710)
 #define SCIF_FNS(name, scif_offset, scif_size) \
   CPU_SCIF_FNS(name, scif_offset, scif_size)
 #else
@@ -362,7 +341,9 @@ struct sci_port {
   CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size)
 #endif
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7710)
 SCIF_FNS(SCSMR,  0x00, 16)
 SCIF_FNS(SCBRR,  0x04,  8)
 SCIF_FNS(SCSCR,  0x08, 16)
@@ -447,7 +428,9 @@ static inline int sci_rxd_in(struct uart_port *port)
                return ctrl_inb(SCSPTR)&0x01 ? 1 : 0; /* SCI */
        return 1;
 }
-#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7706)
 static inline int sci_rxd_in(struct uart_port *port)
 {
        if (port->mapbase == 0xfffffe80)
@@ -467,6 +450,13 @@ static inline int sci_rxd_in(struct uart_port *port)
                return ctrl_inb(SCPDR)&0x10 ? 1 : 0; /* SCIF */
        return 1;
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+       if (port->mapbase == SCSPTR0)
+               return ctrl_inw(SCSPTR0 + 0x10) & 0x01 ? 1 : 0;
+       return 1;
+}
 #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
       defined(CONFIG_CPU_SUBTYPE_SH7751) || \
       defined(CONFIG_CPU_SUBTYPE_SH4_202)
@@ -504,6 +494,19 @@ static inline int sci_rxd_in(struct uart_port *port)
 {
        return ctrl_inb(SCPDR)&0x01 ? 1 : 0; /* SCIF0 */
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+       if (port->mapbase == 0xffe00000)
+               return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffe10000)
+               return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffe20000)
+               return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+       if (port->mapbase == 0xffe30000)
+               return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
+       return 1;
+}
 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 static inline int sci_rxd_in(struct uart_port *port)
 {
@@ -587,4 +590,3 @@ static inline int sci_rxd_in(struct uart_port *port)
 #else /* Generic SH */
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
 #endif
-
index 005043197527142749965cce1d75fde169773c4c..f9b1719b9a372d562da3d65d959123ba1e1243fc 100644 (file)
@@ -25,6 +25,7 @@ config USB_ARCH_HAS_OHCI
        default y if PXA27x
        default y if ARCH_EP93XX
        default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261)
+       default y if ARCH_PNX4008
        # PPC:
        default y if STB03xxx
        default y if PPC_MPC52xx
index 4710eb02ed640b7b572c223e2792759e2ff0a76d..97d57cfc343b628fb81f78820c2ad6cea9e5b958 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_ISP116X_HCD) += host/
 obj-$(CONFIG_USB_OHCI_HCD)     += host/
 obj-$(CONFIG_USB_UHCI_HCD)     += host/
 obj-$(CONFIG_USB_SL811_HCD)    += host/
+obj-$(CONFIG_USB_U132_HCD)     += host/
 obj-$(CONFIG_ETRAX_USB_HOST)   += host/
 obj-$(CONFIG_USB_OHCI_AT91)    += host/
 
@@ -23,6 +24,7 @@ obj-$(CONFIG_USB_PRINTER)     += class/
 obj-$(CONFIG_USB_STORAGE)      += storage/
 obj-$(CONFIG_USB)              += storage/
 
+obj-$(CONFIG_USB_ACECAD)       += input/
 obj-$(CONFIG_USB_AIPTEK)       += input/
 obj-$(CONFIG_USB_ATI_REMOTE)   += input/
 obj-$(CONFIG_USB_HID)          += input/
@@ -31,8 +33,8 @@ obj-$(CONFIG_USB_KBTAB)               += input/
 obj-$(CONFIG_USB_MOUSE)                += input/
 obj-$(CONFIG_USB_MTOUCH)       += input/
 obj-$(CONFIG_USB_POWERMATE)    += input/
+obj-$(CONFIG_USB_TRANCEVIBRATOR)+= input/
 obj-$(CONFIG_USB_WACOM)                += input/
-obj-$(CONFIG_USB_ACECAD)       += input/
 obj-$(CONFIG_USB_XPAD)         += input/
 
 obj-$(CONFIG_USB_CATC)         += net/
@@ -47,22 +49,24 @@ obj-$(CONFIG_USB_MICROTEK)  += image/
 
 obj-$(CONFIG_USB_SERIAL)       += serial/
 
+obj-$(CONFIG_USB_ADUTUX)       += misc/
+obj-$(CONFIG_USB_APPLEDISPLAY) += misc/
 obj-$(CONFIG_USB_AUERSWALD)    += misc/
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/
 obj-$(CONFIG_USB_CYTHERM)      += misc/
 obj-$(CONFIG_USB_EMI26)                += misc/
 obj-$(CONFIG_USB_EMI62)                += misc/
+obj-$(CONFIG_USB_FTDI_ELAN)    += misc/
 obj-$(CONFIG_USB_IDMOUSE)      += misc/
 obj-$(CONFIG_USB_LCD)          += misc/
 obj-$(CONFIG_USB_LD)           += misc/
 obj-$(CONFIG_USB_LED)          += misc/
 obj-$(CONFIG_USB_LEGOTOWER)    += misc/
+obj-$(CONFIG_USB_PHIDGETSERVO) += misc/
 obj-$(CONFIG_USB_RIO500)       += misc/
+obj-$(CONFIG_USB_SISUSBVGA)    += misc/
 obj-$(CONFIG_USB_TEST)         += misc/
 obj-$(CONFIG_USB_USS720)       += misc/
-obj-$(CONFIG_USB_PHIDGETSERVO) += misc/
-obj-$(CONFIG_USB_SISUSBVGA)    += misc/
-obj-$(CONFIG_USB_APPLEDISPLAY) += misc/
 
 obj-$(CONFIG_USB_ATM)          += atm/
 obj-$(CONFIG_USB_SPEEDTOUCH)   += atm/
index b38990adf1cdaf7d15b1a3249350e840461bac6a..465961a26e4a9131af4fe96671fe42eac202c16f 100644 (file)
@@ -1621,26 +1621,32 @@ static int claim_interface(struct usb_device *usb_dev,
        return ret;
 }
 
-static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+static struct attribute *attrs[] = {
+       &dev_attr_stat_status.attr,
+       &dev_attr_stat_mflags.attr,
+       &dev_attr_stat_human_status.attr,
+       &dev_attr_stat_delin.attr,
+       &dev_attr_stat_vidcpe.attr,
+       &dev_attr_stat_usrate.attr,
+       &dev_attr_stat_dsrate.attr,
+       &dev_attr_stat_usattenuation.attr,
+       &dev_attr_stat_dsattenuation.attr,
+       &dev_attr_stat_usmargin.attr,
+       &dev_attr_stat_dsmargin.attr,
+       &dev_attr_stat_txflow.attr,
+       &dev_attr_stat_rxflow.attr,
+       &dev_attr_stat_uscorr.attr,
+       &dev_attr_stat_dscorr.attr,
+       &dev_attr_stat_usunc.attr,
+       &dev_attr_stat_dsunc.attr,
+};
+static struct attribute_group attr_grp = {
+       .attrs = attrs,
+};
+
+static int create_fs_entries(struct usb_interface *intf)
 {
-       /* sysfs interface */
-       device_create_file(&intf->dev, &dev_attr_stat_status);
-       device_create_file(&intf->dev, &dev_attr_stat_mflags);
-       device_create_file(&intf->dev, &dev_attr_stat_human_status);
-       device_create_file(&intf->dev, &dev_attr_stat_delin);
-       device_create_file(&intf->dev, &dev_attr_stat_vidcpe);
-       device_create_file(&intf->dev, &dev_attr_stat_usrate);
-       device_create_file(&intf->dev, &dev_attr_stat_dsrate);
-       device_create_file(&intf->dev, &dev_attr_stat_usattenuation);
-       device_create_file(&intf->dev, &dev_attr_stat_dsattenuation);
-       device_create_file(&intf->dev, &dev_attr_stat_usmargin);
-       device_create_file(&intf->dev, &dev_attr_stat_dsmargin);
-       device_create_file(&intf->dev, &dev_attr_stat_txflow);
-       device_create_file(&intf->dev, &dev_attr_stat_rxflow);
-       device_create_file(&intf->dev, &dev_attr_stat_uscorr);
-       device_create_file(&intf->dev, &dev_attr_stat_dscorr);
-       device_create_file(&intf->dev, &dev_attr_stat_usunc);
-       device_create_file(&intf->dev, &dev_attr_stat_dsunc);
+       return sysfs_create_group(&intf->dev.kobj, &attr_grp);
 }
 
 static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
@@ -1708,37 +1714,25 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
                return ret;
        }
 
-       create_fs_entries(sc, intf);
+       ret = create_fs_entries(intf);
+       if (ret) {
+               uea_stop(sc);
+               kfree(sc);
+               return ret;
+       }
        return 0;
 }
 
-static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
+static void destroy_fs_entries(struct usb_interface *intf)
 {
-       /* sysfs interface */
-       device_remove_file(&intf->dev, &dev_attr_stat_status);
-       device_remove_file(&intf->dev, &dev_attr_stat_mflags);
-       device_remove_file(&intf->dev, &dev_attr_stat_human_status);
-       device_remove_file(&intf->dev, &dev_attr_stat_delin);
-       device_remove_file(&intf->dev, &dev_attr_stat_vidcpe);
-       device_remove_file(&intf->dev, &dev_attr_stat_usrate);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsrate);
-       device_remove_file(&intf->dev, &dev_attr_stat_usattenuation);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation);
-       device_remove_file(&intf->dev, &dev_attr_stat_usmargin);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsmargin);
-       device_remove_file(&intf->dev, &dev_attr_stat_txflow);
-       device_remove_file(&intf->dev, &dev_attr_stat_rxflow);
-       device_remove_file(&intf->dev, &dev_attr_stat_uscorr);
-       device_remove_file(&intf->dev, &dev_attr_stat_dscorr);
-       device_remove_file(&intf->dev, &dev_attr_stat_usunc);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsunc);
+       sysfs_remove_group(&intf->dev.kobj, &attr_grp);
 }
 
 static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)
 {
        struct uea_softc *sc = usbatm->driver_data;
 
-       destroy_fs_entries(sc, intf);
+       destroy_fs_entries(intf);
        uea_stop(sc);
        kfree(sc);
 }
index 48dee4b8d8e50a8b6064fb5b2e98b29fc2293e91..9cac11ca1bb73f83cada5a12f77bf4f6ebb4fc11 100644 (file)
@@ -813,7 +813,7 @@ static unsigned int usblp_quirks (__u16 vendor, __u16 product)
        return 0;
 }
 
-static struct file_operations usblp_fops = {
+static const struct file_operations usblp_fops = {
        .owner =        THIS_MODULE,
        .read =         usblp_read,
        .write =        usblp_write,
@@ -927,7 +927,9 @@ static int usblp_probe(struct usb_interface *intf,
 
        /* Retrieve and store the device ID string. */
        usblp_cache_device_id_string(usblp);
-       device_create_file(&intf->dev, &dev_attr_ieee1284_id);
+       retval = device_create_file(&intf->dev, &dev_attr_ieee1284_id);
+       if (retval)
+               goto abort_intfdata;
 
 #ifdef DEBUG
        usblp_check_status(usblp, 0);
@@ -1021,18 +1023,13 @@ static int usblp_select_alts(struct usblp *usblp)
                for (e = 0; e < ifd->desc.bNumEndpoints; e++) {
                        epd = &ifd->endpoint[e].desc;
 
-                       if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
-                           USB_ENDPOINT_XFER_BULK)
-                               continue;
-
-                       if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
+                       if (usb_endpoint_is_bulk_out(epd))
                                if (!epwrite)
                                        epwrite = epd;
 
-                       } else {
+                       if (usb_endpoint_is_bulk_in(epd))
                                if (!epread)
                                        epread = epd;
-                       }
                }
 
                /* Ignore buggy hardware without the right endpoints. */
index ec510922af63a1fac195a022b1347ff4d2624c78..34e9bac319b4e5af731727e5da58907f28612a61 100644 (file)
@@ -4,7 +4,7 @@
 
 usbcore-objs   := usb.o hub.o hcd.o urb.o message.o driver.o \
                        config.o file.o buffer.o sysfs.o endpoint.o \
-                       devio.o notify.o
+                       devio.o notify.o generic.o
 
 ifeq ($(CONFIG_PCI),y)
        usbcore-objs    += hcd-pci.o
index f4f4ef0f377ae001c2aee0d24bec14dc91a46442..840442a25b6183844979b3c2f5fc58d3607fb7ac 100644 (file)
@@ -104,7 +104,7 @@ void *hcd_buffer_alloc (
        dma_addr_t              *dma
 )
 {
-       struct usb_hcd          *hcd = bus->hcpriv;
+       struct usb_hcd          *hcd = bus_to_hcd(bus);
        int                     i;
 
        /* some USB hosts just use PIO */
@@ -127,7 +127,7 @@ void hcd_buffer_free (
        dma_addr_t              dma
 )
 {
-       struct usb_hcd          *hcd = bus->hcpriv;
+       struct usb_hcd          *hcd = bus_to_hcd(bus);
        int                     i;
 
        if (!addr)
index 4c9e63e665b6988f54f4feca6566a4d6444c231e..bfb3731d42db816531a4cacd69d692ff04727827 100644 (file)
@@ -475,7 +475,9 @@ int usb_get_configuration(struct usb_device *dev)
                if (result < 0) {
                        dev_err(ddev, "unable to read config index %d "
                            "descriptor/%s\n", cfgno, "start");
-                       goto err;
+                       dev_err(ddev, "chopping to %d config(s)\n", cfgno);
+                       dev->descriptor.bNumConfigurations = cfgno;
+                       break;
                } else if (result < 4) {
                        dev_err(ddev, "config index %d descriptor too short "
                            "(expected %i, got %i)\n", cfgno,
index c0f37343a276ce551705065625f923ec13f7f629..3538c2fdadfe5752fc650cc858fd2ab76de32ff5 100644 (file)
@@ -593,7 +593,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte
 /* Kernel lock for "lastev" protection */
 static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
 {
-       struct usb_device_status *st = (struct usb_device_status *)file->private_data;
+       struct usb_device_status *st = file->private_data;
        unsigned int mask = 0;
 
        lock_kernel();
@@ -603,7 +603,7 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
                        unlock_kernel();
                        return POLLIN;
                }
-               
+
                /* we may have dropped BKL - need to check for having lost the race */
                if (file->private_data) {
                        kfree(st);
@@ -667,7 +667,7 @@ static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig)
        return ret;
 }
 
-struct file_operations usbfs_devices_fops = {
+const struct file_operations usbfs_devices_fops = {
        .llseek =       usb_device_lseek,
        .read =         usb_device_read,
        .poll =         usb_device_poll,
index 218621b9958e4af20972900bc19038d940fbe78a..a94c63bef632c5151e985073f2cf6457f30a0ad4 100644 (file)
@@ -59,6 +59,9 @@
 #define USB_DEVICE_MAX                 USB_MAXBUS * 128
 static struct class *usb_device_class;
 
+/* Mutual exclusion for removal, open, and release */
+DEFINE_MUTEX(usbfs_mutex);
+
 struct async {
        struct list_head asynclist;
        struct dev_state *ps;
@@ -87,9 +90,10 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
 
 #define        MAX_USBFS_BUFFER_SIZE   16384
 
-static inline int connected (struct usb_device *dev)
+static inline int connected (struct dev_state *ps)
 {
-       return dev->state != USB_STATE_NOTATTACHED;
+       return (!list_empty(&ps->list) &&
+                       ps->dev->state != USB_STATE_NOTATTACHED);
 }
 
 static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
@@ -118,7 +122,7 @@ static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
 
 static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
 {
-       struct dev_state *ps = (struct dev_state *)file->private_data;
+       struct dev_state *ps = file->private_data;
        struct usb_device *dev = ps->dev;
        ssize_t ret = 0;
        unsigned len;
@@ -127,7 +131,7 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l
 
        pos = *ppos;
        usb_lock_device(dev);
-       if (!connected(dev)) {
+       if (!connected(ps)) {
                ret = -ENODEV;
                goto err;
        } else if (pos < 0) {
@@ -301,7 +305,7 @@ static void snoop_urb(struct urb *urb, void __user *userurb)
 
 static void async_completed(struct urb *urb, struct pt_regs *regs)
 {
-        struct async *as = (struct async *)urb->context;
+        struct async *as = urb->context;
         struct dev_state *ps = as->ps;
        struct siginfo sinfo;
 
@@ -541,25 +545,25 @@ static int usbdev_open(struct inode *inode, struct file *file)
        struct dev_state *ps;
        int ret;
 
-       /* 
-        * no locking necessary here, as chrdev_open has the kernel lock
-        * (still acquire the kernel lock for safety)
-        */
+       /* Protect against simultaneous removal or release */
+       mutex_lock(&usbfs_mutex);
+
        ret = -ENOMEM;
        if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
-               goto out_nolock;
+               goto out;
 
-       lock_kernel();
        ret = -ENOENT;
        /* check if we are called from a real node or usbfs */
        if (imajor(inode) == USB_DEVICE_MAJOR)
                dev = usbdev_lookup_minor(iminor(inode));
        if (!dev)
-               dev = inode->u.generic_ip;
-       if (!dev) {
-               kfree(ps);
+               dev = inode->i_private;
+       if (!dev)
                goto out;
-       }
+       ret = usb_autoresume_device(dev, 1);
+       if (ret)
+               goto out;
+
        usb_get_dev(dev);
        ret = 0;
        ps->dev = dev;
@@ -579,30 +583,36 @@ static int usbdev_open(struct inode *inode, struct file *file)
        list_add_tail(&ps->list, &dev->filelist);
        file->private_data = ps;
  out:
-       unlock_kernel();
- out_nolock:
-        return ret;
+       if (ret)
+               kfree(ps);
+       mutex_unlock(&usbfs_mutex);
+       return ret;
 }
 
 static int usbdev_release(struct inode *inode, struct file *file)
 {
-       struct dev_state *ps = (struct dev_state *)file->private_data;
+       struct dev_state *ps = file->private_data;
        struct usb_device *dev = ps->dev;
        unsigned int ifnum;
 
        usb_lock_device(dev);
+
+       /* Protect against simultaneous open */
+       mutex_lock(&usbfs_mutex);
        list_del_init(&ps->list);
+       mutex_unlock(&usbfs_mutex);
+
        for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed);
                        ifnum++) {
                if (test_bit(ifnum, &ps->ifclaimed))
                        releaseintf(ps, ifnum);
        }
        destroy_all_async(ps);
+       usb_autosuspend_device(dev, 1);
        usb_unlock_device(dev);
        usb_put_dev(dev);
-       ps->dev = NULL;
        kfree(ps);
-        return 0;
+       return 0;
 }
 
 static int proc_control(struct dev_state *ps, void __user *arg)
@@ -1322,7 +1332,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
                }
        }
 
-       if (!connected(ps->dev)) {
+       if (!connected(ps)) {
                kfree(buf);
                return -ENODEV;
        }
@@ -1349,7 +1359,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
        /* let kernel drivers try to (re)bind to the interface */
        case USBDEVFS_CONNECT:
                usb_unlock_device(ps->dev);
-               bus_rescan_devices(intf->dev.bus);
+               retval = bus_rescan_devices(intf->dev.bus);
                usb_lock_device(ps->dev);
                break;
 
@@ -1413,7 +1423,7 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg)
  */
 static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
-       struct dev_state *ps = (struct dev_state *)file->private_data;
+       struct dev_state *ps = file->private_data;
        struct usb_device *dev = ps->dev;
        void __user *p = (void __user *)arg;
        int ret = -ENOTTY;
@@ -1421,7 +1431,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        if (!(file->f_mode & FMODE_WRITE))
                return -EPERM;
        usb_lock_device(dev);
-       if (!connected(dev)) {
+       if (!connected(ps)) {
                usb_unlock_device(dev);
                return -ENODEV;
        }
@@ -1556,18 +1566,18 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 /* No kernel lock - fine */
 static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
 {
-       struct dev_state *ps = (struct dev_state *)file->private_data;
-        unsigned int mask = 0;
+       struct dev_state *ps = file->private_data;
+       unsigned int mask = 0;
 
        poll_wait(file, &ps->wait, wait);
        if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
                mask |= POLLOUT | POLLWRNORM;
-       if (!connected(ps->dev))
+       if (!connected(ps))
                mask |= POLLERR | POLLHUP;
        return mask;
 }
 
-struct file_operations usbfs_device_file_operations = {
+const struct file_operations usbfs_device_file_operations = {
        .llseek =       usbdev_lseek,
        .read =         usbdev_read,
        .poll =         usbdev_poll,
index ec8906501415b38cac0298e52194874ff58a1c2f..b10463244413c276846bbdcaebe58a0026ba4cbd 100644 (file)
@@ -17,7 +17,8 @@
  *
  * NOTE! This is not actually a driver at all, rather this is
  * just a collection of helper routines that implement the
- * generic USB things that the real drivers can use..
+ * matching, probing, releasing, suspending and resuming for
+ * real drivers.
  *
  */
 
@@ -34,38 +35,6 @@ struct usb_dynid {
        struct usb_device_id id;
 };
 
-
-static int generic_probe(struct device *dev)
-{
-       return 0;
-}
-static int generic_remove(struct device *dev)
-{
-       struct usb_device *udev = to_usb_device(dev);
-
-       /* if this is only an unbind, not a physical disconnect, then
-        * unconfigure the device */
-       if (udev->state == USB_STATE_CONFIGURED)
-               usb_set_configuration(udev, 0);
-
-       /* in case the call failed or the device was suspended */
-       if (udev->state >= USB_STATE_CONFIGURED)
-               usb_disable_device(udev, 0);
-       return 0;
-}
-
-struct device_driver usb_generic_driver = {
-       .owner = THIS_MODULE,
-       .name = "usb",
-       .bus = &usb_bus_type,
-       .probe = generic_probe,
-       .remove = generic_remove,
-};
-
-/* Fun hack to determine if the struct device is a
- * usb device or a usb interface. */
-int usb_generic_driver_data;
-
 #ifdef CONFIG_HOTPLUG
 
 /*
@@ -80,6 +49,7 @@ static ssize_t store_new_id(struct device_driver *driver,
        u32 idVendor = 0;
        u32 idProduct = 0;
        int fields = 0;
+       int retval = 0;
 
        fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
        if (fields < 2)
@@ -99,10 +69,12 @@ static ssize_t store_new_id(struct device_driver *driver,
        spin_unlock(&usb_drv->dynids.lock);
 
        if (get_driver(driver)) {
-               driver_attach(driver);
+               retval = driver_attach(driver);
                put_driver(driver);
        }
 
+       if (retval)
+               return retval;
        return count;
 }
 static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
@@ -115,7 +87,7 @@ static int usb_create_newid_file(struct usb_driver *usb_drv)
                goto exit;
 
        if (usb_drv->probe != NULL)
-               error = sysfs_create_file(&usb_drv->driver.kobj,
+               error = sysfs_create_file(&usb_drv->drvwrap.driver.kobj,
                                          &driver_attr_new_id.attr);
 exit:
        return error;
@@ -127,7 +99,7 @@ static void usb_remove_newid_file(struct usb_driver *usb_drv)
                return;
 
        if (usb_drv->probe != NULL)
-               sysfs_remove_file(&usb_drv->driver.kobj,
+               sysfs_remove_file(&usb_drv->drvwrap.driver.kobj,
                                  &driver_attr_new_id.attr);
 }
 
@@ -174,21 +146,57 @@ static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *in
 }
 
 
-/* called from driver core with usb_bus_type.subsys writelock */
+/* called from driver core with dev locked */
+static int usb_probe_device(struct device *dev)
+{
+       struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
+       struct usb_device *udev;
+       int error = -ENODEV;
+
+       dev_dbg(dev, "%s\n", __FUNCTION__);
+
+       if (!is_usb_device(dev))        /* Sanity check */
+               return error;
+
+       udev = to_usb_device(dev);
+
+       /* TODO: Add real matching code */
+
+       /* The device should always appear to be in use
+        * unless the driver suports autosuspend.
+        */
+       udev->pm_usage_cnt = !(udriver->supports_autosuspend);
+
+       error = udriver->probe(udev);
+       return error;
+}
+
+/* called from driver core with dev locked */
+static int usb_unbind_device(struct device *dev)
+{
+       struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
+
+       udriver->disconnect(to_usb_device(dev));
+       return 0;
+}
+
+
+/* called from driver core with dev locked */
 static int usb_probe_interface(struct device *dev)
 {
-       struct usb_interface * intf = to_usb_interface(dev);
-       struct usb_driver * driver = to_usb_driver(dev->driver);
+       struct usb_driver *driver = to_usb_driver(dev->driver);
+       struct usb_interface *intf;
+       struct usb_device *udev;
        const struct usb_device_id *id;
        int error = -ENODEV;
 
        dev_dbg(dev, "%s\n", __FUNCTION__);
 
-       if (!driver->probe)
+       if (is_usb_device(dev))         /* Sanity check */
                return error;
-       /* FIXME we'd much prefer to just resume it ... */
-       if (interface_to_usbdev(intf)->state == USB_STATE_SUSPENDED)
-               return -EHOSTUNREACH;
+
+       intf = to_usb_interface(dev);
+       udev = interface_to_usbdev(intf);
 
        id = usb_match_id(intf, driver->id_table);
        if (!id)
@@ -196,48 +204,165 @@ static int usb_probe_interface(struct device *dev)
        if (id) {
                dev_dbg(dev, "%s - got id\n", __FUNCTION__);
 
+               error = usb_autoresume_device(udev, 1);
+               if (error)
+                       return error;
+
                /* Interface "power state" doesn't correspond to any hardware
                 * state whatsoever.  We use it to record when it's bound to
                 * a driver that may start I/0:  it's not frozen/quiesced.
                 */
                mark_active(intf);
                intf->condition = USB_INTERFACE_BINDING;
+
+               /* The interface should always appear to be in use
+                * unless the driver suports autosuspend.
+                */
+               intf->pm_usage_cnt = !(driver->supports_autosuspend);
+
                error = driver->probe(intf, id);
                if (error) {
                        mark_quiesced(intf);
+                       intf->needs_remote_wakeup = 0;
                        intf->condition = USB_INTERFACE_UNBOUND;
                } else
                        intf->condition = USB_INTERFACE_BOUND;
+
+               usb_autosuspend_device(udev, 1);
        }
 
        return error;
 }
 
-/* called from driver core with usb_bus_type.subsys writelock */
+/* called from driver core with dev locked */
 static int usb_unbind_interface(struct device *dev)
 {
+       struct usb_driver *driver = to_usb_driver(dev->driver);
        struct usb_interface *intf = to_usb_interface(dev);
-       struct usb_driver *driver = to_usb_driver(intf->dev.driver);
+       struct usb_device *udev;
+       int error;
 
        intf->condition = USB_INTERFACE_UNBINDING;
 
+       /* Autoresume for set_interface call below */
+       udev = interface_to_usbdev(intf);
+       error = usb_autoresume_device(udev, 1);
+
        /* release all urbs for this interface */
        usb_disable_interface(interface_to_usbdev(intf), intf);
 
-       if (driver && driver->disconnect)
-               driver->disconnect(intf);
+       driver->disconnect(intf);
 
        /* reset other interface state */
        usb_set_interface(interface_to_usbdev(intf),
                        intf->altsetting[0].desc.bInterfaceNumber,
                        0);
        usb_set_intfdata(intf, NULL);
+
        intf->condition = USB_INTERFACE_UNBOUND;
        mark_quiesced(intf);
+       intf->needs_remote_wakeup = 0;
+
+       if (!error)
+               usb_autosuspend_device(udev, 1);
 
        return 0;
 }
 
+/**
+ * usb_driver_claim_interface - bind a driver to an interface
+ * @driver: the driver to be bound
+ * @iface: the interface to which it will be bound; must be in the
+ *     usb device's active configuration
+ * @priv: driver data associated with that interface
+ *
+ * This is used by usb device drivers that need to claim more than one
+ * interface on a device when probing (audio and acm are current examples).
+ * No device driver should directly modify internal usb_interface or
+ * usb_device structure members.
+ *
+ * Few drivers should need to use this routine, since the most natural
+ * way to bind to an interface is to return the private data from
+ * the driver's probe() method.
+ *
+ * Callers must own the device lock and the driver model's usb_bus_type.subsys
+ * writelock.  So driver probe() entries don't need extra locking,
+ * but other call contexts may need to explicitly claim those locks.
+ */
+int usb_driver_claim_interface(struct usb_driver *driver,
+                               struct usb_interface *iface, void* priv)
+{
+       struct device *dev = &iface->dev;
+       struct usb_device *udev = interface_to_usbdev(iface);
+       int retval = 0;
+
+       if (dev->driver)
+               return -EBUSY;
+
+       dev->driver = &driver->drvwrap.driver;
+       usb_set_intfdata(iface, priv);
+
+       mutex_lock_nested(&udev->pm_mutex, udev->level);
+       iface->condition = USB_INTERFACE_BOUND;
+       mark_active(iface);
+       iface->pm_usage_cnt = !(driver->supports_autosuspend);
+       mutex_unlock(&udev->pm_mutex);
+
+       /* if interface was already added, bind now; else let
+        * the future device_add() bind it, bypassing probe()
+        */
+       if (device_is_registered(dev))
+               retval = device_bind_driver(dev);
+
+       return retval;
+}
+EXPORT_SYMBOL(usb_driver_claim_interface);
+
+/**
+ * usb_driver_release_interface - unbind a driver from an interface
+ * @driver: the driver to be unbound
+ * @iface: the interface from which it will be unbound
+ *
+ * This can be used by drivers to release an interface without waiting
+ * for their disconnect() methods to be called.  In typical cases this
+ * also causes the driver disconnect() method to be called.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ * Callers must own the device lock and the driver model's usb_bus_type.subsys
+ * writelock.  So driver disconnect() entries don't need extra locking,
+ * but other call contexts may need to explicitly claim those locks.
+ */
+void usb_driver_release_interface(struct usb_driver *driver,
+                                       struct usb_interface *iface)
+{
+       struct device *dev = &iface->dev;
+       struct usb_device *udev = interface_to_usbdev(iface);
+
+       /* this should never happen, don't release something that's not ours */
+       if (!dev->driver || dev->driver != &driver->drvwrap.driver)
+               return;
+
+       /* don't release from within disconnect() */
+       if (iface->condition != USB_INTERFACE_BOUND)
+               return;
+
+       /* don't release if the interface hasn't been added yet */
+       if (device_is_registered(dev)) {
+               iface->condition = USB_INTERFACE_UNBINDING;
+               device_release_driver(dev);
+       }
+
+       dev->driver = NULL;
+       usb_set_intfdata(iface, NULL);
+
+       mutex_lock_nested(&udev->pm_mutex, udev->level);
+       iface->condition = USB_INTERFACE_UNBOUND;
+       mark_quiesced(iface);
+       iface->needs_remote_wakeup = 0;
+       mutex_unlock(&udev->pm_mutex);
+}
+EXPORT_SYMBOL(usb_driver_release_interface);
+
 /* returns 0 if no match, 1 if match */
 static int usb_match_one_id(struct usb_interface *interface,
                            const struct usb_device_id *id)
@@ -380,36 +505,224 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
 EXPORT_SYMBOL_GPL_FUTURE(usb_match_id);
 
 int usb_device_match(struct device *dev, struct device_driver *drv)
+{
+       /* devices and interfaces are handled separately */
+       if (is_usb_device(dev)) {
+
+               /* interface drivers never match devices */
+               if (!is_usb_device_driver(drv))
+                       return 0;
+
+               /* TODO: Add real matching code */
+               return 1;
+
+       } else {
+               struct usb_interface *intf;
+               struct usb_driver *usb_drv;
+               const struct usb_device_id *id;
+
+               /* device drivers never match interfaces */
+               if (is_usb_device_driver(drv))
+                       return 0;
+
+               intf = to_usb_interface(dev);
+               usb_drv = to_usb_driver(drv);
+
+               id = usb_match_id(intf, usb_drv->id_table);
+               if (id)
+                       return 1;
+
+               id = usb_match_dynamic_id(intf, usb_drv);
+               if (id)
+                       return 1;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_HOTPLUG
+
+/*
+ * This sends an uevent to userspace, typically helping to load driver
+ * or other modules, configure the device, and more.  Drivers can provide
+ * a MODULE_DEVICE_TABLE to help with module loading subtasks.
+ *
+ * We're called either from khubd (the typical case) or from root hub
+ * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
+ * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the
+ * device (and this configuration!) are still present.
+ */
+static int usb_uevent(struct device *dev, char **envp, int num_envp,
+                     char *buffer, int buffer_size)
 {
        struct usb_interface *intf;
-       struct usb_driver *usb_drv;
-       const struct usb_device_id *id;
+       struct usb_device *usb_dev;
+       struct usb_host_interface *alt;
+       int i = 0;
+       int length = 0;
 
-       /* check for generic driver, which we don't match any device with */
-       if (drv == &usb_generic_driver)
-               return 0;
+       if (!dev)
+               return -ENODEV;
 
-       intf = to_usb_interface(dev);
-       usb_drv = to_usb_driver(drv);
+       /* driver is often null here; dev_dbg() would oops */
+       pr_debug ("usb %s: uevent\n", dev->bus_id);
 
-       id = usb_match_id(intf, usb_drv->id_table);
-       if (id)
-               return 1;
+       if (is_usb_device(dev)) {
+               usb_dev = to_usb_device(dev);
+               alt = NULL;
+       } else {
+               intf = to_usb_interface(dev);
+               usb_dev = interface_to_usbdev(intf);
+               alt = intf->cur_altsetting;
+       }
+
+       if (usb_dev->devnum < 0) {
+               pr_debug ("usb %s: already deleted?\n", dev->bus_id);
+               return -ENODEV;
+       }
+       if (!usb_dev->bus) {
+               pr_debug ("usb %s: bus removed?\n", dev->bus_id);
+               return -ENODEV;
+       }
+
+#ifdef CONFIG_USB_DEVICEFS
+       /* If this is available, userspace programs can directly read
+        * all the device descriptors we don't tell them about.  Or
+        * even act as usermode drivers.
+        *
+        * FIXME reduce hardwired intelligence here
+        */
+       if (add_uevent_var(envp, num_envp, &i,
+                          buffer, buffer_size, &length,
+                          "DEVICE=/proc/bus/usb/%03d/%03d",
+                          usb_dev->bus->busnum, usb_dev->devnum))
+               return -ENOMEM;
+#endif
+
+       /* per-device configurations are common */
+       if (add_uevent_var(envp, num_envp, &i,
+                          buffer, buffer_size, &length,
+                          "PRODUCT=%x/%x/%x",
+                          le16_to_cpu(usb_dev->descriptor.idVendor),
+                          le16_to_cpu(usb_dev->descriptor.idProduct),
+                          le16_to_cpu(usb_dev->descriptor.bcdDevice)))
+               return -ENOMEM;
+
+       /* class-based driver binding models */
+       if (add_uevent_var(envp, num_envp, &i,
+                          buffer, buffer_size, &length,
+                          "TYPE=%d/%d/%d",
+                          usb_dev->descriptor.bDeviceClass,
+                          usb_dev->descriptor.bDeviceSubClass,
+                          usb_dev->descriptor.bDeviceProtocol))
+               return -ENOMEM;
+
+       if (!is_usb_device(dev)) {
+
+               if (add_uevent_var(envp, num_envp, &i,
+                          buffer, buffer_size, &length,
+                          "INTERFACE=%d/%d/%d",
+                          alt->desc.bInterfaceClass,
+                          alt->desc.bInterfaceSubClass,
+                          alt->desc.bInterfaceProtocol))
+                       return -ENOMEM;
+
+               if (add_uevent_var(envp, num_envp, &i,
+                          buffer, buffer_size, &length,
+                          "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
+                          le16_to_cpu(usb_dev->descriptor.idVendor),
+                          le16_to_cpu(usb_dev->descriptor.idProduct),
+                          le16_to_cpu(usb_dev->descriptor.bcdDevice),
+                          usb_dev->descriptor.bDeviceClass,
+                          usb_dev->descriptor.bDeviceSubClass,
+                          usb_dev->descriptor.bDeviceProtocol,
+                          alt->desc.bInterfaceClass,
+                          alt->desc.bInterfaceSubClass,
+                          alt->desc.bInterfaceProtocol))
+                       return -ENOMEM;
+       }
+
+       envp[i] = NULL;
 
-       id = usb_match_dynamic_id(intf, usb_drv);
-       if (id)
-               return 1;
        return 0;
 }
 
+#else
+
+static int usb_uevent(struct device *dev, char **envp,
+                       int num_envp, char *buffer, int buffer_size)
+{
+       return -ENODEV;
+}
+
+#endif /* CONFIG_HOTPLUG */
+
+/**
+ * usb_register_device_driver - register a USB device (not interface) driver
+ * @new_udriver: USB operations for the device driver
+ * @owner: module owner of this driver.
+ *
+ * Registers a USB device driver with the USB core.  The list of
+ * unattached devices will be rescanned whenever a new driver is
+ * added, allowing the new driver to attach to any recognized devices.
+ * Returns a negative error code on failure and 0 on success.
+ */
+int usb_register_device_driver(struct usb_device_driver *new_udriver,
+               struct module *owner)
+{
+       int retval = 0;
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       new_udriver->drvwrap.for_devices = 1;
+       new_udriver->drvwrap.driver.name = (char *) new_udriver->name;
+       new_udriver->drvwrap.driver.bus = &usb_bus_type;
+       new_udriver->drvwrap.driver.probe = usb_probe_device;
+       new_udriver->drvwrap.driver.remove = usb_unbind_device;
+       new_udriver->drvwrap.driver.owner = owner;
+
+       retval = driver_register(&new_udriver->drvwrap.driver);
+
+       if (!retval) {
+               pr_info("%s: registered new device driver %s\n",
+                       usbcore_name, new_udriver->name);
+               usbfs_update_special();
+       } else {
+               printk(KERN_ERR "%s: error %d registering device "
+                       "       driver %s\n",
+                       usbcore_name, retval, new_udriver->name);
+       }
+
+       return retval;
+}
+EXPORT_SYMBOL_GPL(usb_register_device_driver);
+
+/**
+ * usb_deregister_device_driver - unregister a USB device (not interface) driver
+ * @udriver: USB operations of the device driver to unregister
+ * Context: must be able to sleep
+ *
+ * Unlinks the specified driver from the internal USB driver list.
+ */
+void usb_deregister_device_driver(struct usb_device_driver *udriver)
+{
+       pr_info("%s: deregistering device driver %s\n",
+                       usbcore_name, udriver->name);
+
+       driver_unregister(&udriver->drvwrap.driver);
+       usbfs_update_special();
+}
+EXPORT_SYMBOL_GPL(usb_deregister_device_driver);
+
 /**
- * usb_register_driver - register a USB driver
- * @new_driver: USB operations for the driver
+ * usb_register_driver - register a USB interface driver
+ * @new_driver: USB operations for the interface driver
  * @owner: module owner of this driver.
  *
- * Registers a USB driver with the USB core.  The list of unattached
- * interfaces will be rescanned whenever a new driver is added, allowing
- * the new driver to attach to any recognized devices.
+ * Registers a USB interface driver with the USB core.  The list of
+ * unattached interfaces will be rescanned whenever a new driver is
+ * added, allowing the new driver to attach to any recognized interfaces.
  * Returns a negative error code on failure and 0 on success.
  *
  * NOTE: if you want your driver to use the USB major number, you must call
@@ -423,23 +736,25 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
        if (usb_disabled())
                return -ENODEV;
 
-       new_driver->driver.name = (char *)new_driver->name;
-       new_driver->driver.bus = &usb_bus_type;
-       new_driver->driver.probe = usb_probe_interface;
-       new_driver->driver.remove = usb_unbind_interface;
-       new_driver->driver.owner = owner;
+       new_driver->drvwrap.for_devices = 0;
+       new_driver->drvwrap.driver.name = (char *) new_driver->name;
+       new_driver->drvwrap.driver.bus = &usb_bus_type;
+       new_driver->drvwrap.driver.probe = usb_probe_interface;
+       new_driver->drvwrap.driver.remove = usb_unbind_interface;
+       new_driver->drvwrap.driver.owner = owner;
        spin_lock_init(&new_driver->dynids.lock);
        INIT_LIST_HEAD(&new_driver->dynids.list);
 
-       retval = driver_register(&new_driver->driver);
+       retval = driver_register(&new_driver->drvwrap.driver);
 
        if (!retval) {
-               pr_info("%s: registered new driver %s\n",
+               pr_info("%s: registered new interface driver %s\n",
                        usbcore_name, new_driver->name);
                usbfs_update_special();
                usb_create_newid_file(new_driver);
        } else {
-               printk(KERN_ERR "%s: error %d registering driver %s\n",
+               printk(KERN_ERR "%s: error %d registering interface "
+                       "       driver %s\n",
                        usbcore_name, retval, new_driver->name);
        }
 
@@ -448,8 +763,8 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
 EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver);
 
 /**
- * usb_deregister - unregister a USB driver
- * @driver: USB operations of the driver to unregister
+ * usb_deregister - unregister a USB interface driver
+ * @driver: USB operations of the interface driver to unregister
  * Context: must be able to sleep
  *
  * Unlinks the specified driver from the internal USB driver list.
@@ -460,12 +775,554 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_register_driver);
  */
 void usb_deregister(struct usb_driver *driver)
 {
-       pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);
+       pr_info("%s: deregistering interface driver %s\n",
+                       usbcore_name, driver->name);
 
        usb_remove_newid_file(driver);
        usb_free_dynids(driver);
-       driver_unregister(&driver->driver);
+       driver_unregister(&driver->drvwrap.driver);
 
        usbfs_update_special();
 }
 EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
+
+#ifdef CONFIG_PM
+
+/* Caller has locked udev->pm_mutex */
+static int suspend_device(struct usb_device *udev, pm_message_t msg)
+{
+       struct usb_device_driver        *udriver;
+       int                             status = 0;
+
+       if (udev->state == USB_STATE_NOTATTACHED ||
+                       udev->state == USB_STATE_SUSPENDED)
+               goto done;
+
+       /* For devices that don't have a driver, we do a standard suspend. */
+       if (udev->dev.driver == NULL) {
+               udev->do_remote_wakeup = 0;
+               status = usb_port_suspend(udev);
+               goto done;
+       }
+
+       udriver = to_usb_device_driver(udev->dev.driver);
+       status = udriver->suspend(udev, msg);
+
+done:
+       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       if (status == 0)
+               udev->dev.power.power_state.event = msg.event;
+       return status;
+}
+
+/* Caller has locked udev->pm_mutex */
+static int resume_device(struct usb_device *udev)
+{
+       struct usb_device_driver        *udriver;
+       int                             status = 0;
+
+       if (udev->state == USB_STATE_NOTATTACHED ||
+                       udev->state != USB_STATE_SUSPENDED)
+               goto done;
+
+       /* Can't resume it if it doesn't have a driver. */
+       if (udev->dev.driver == NULL) {
+               status = -ENOTCONN;
+               goto done;
+       }
+
+       udriver = to_usb_device_driver(udev->dev.driver);
+       status = udriver->resume(udev);
+
+done:
+       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       if (status == 0)
+               udev->dev.power.power_state.event = PM_EVENT_ON;
+       return status;
+}
+
+/* Caller has locked intf's usb_device's pm_mutex */
+static int suspend_interface(struct usb_interface *intf, pm_message_t msg)
+{
+       struct usb_driver       *driver;
+       int                     status = 0;
+
+       /* with no hardware, USB interfaces only use FREEZE and ON states */
+       if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
+                       !is_active(intf))
+               goto done;
+
+       if (intf->condition == USB_INTERFACE_UNBOUND)   /* This can't happen */
+               goto done;
+       driver = to_usb_driver(intf->dev.driver);
+
+       if (driver->suspend && driver->resume) {
+               status = driver->suspend(intf, msg);
+               if (status == 0)
+                       mark_quiesced(intf);
+               else if (!interface_to_usbdev(intf)->auto_pm)
+                       dev_err(&intf->dev, "%s error %d\n",
+                                       "suspend", status);
+       } else {
+               // FIXME else if there's no suspend method, disconnect...
+               // Not possible if auto_pm is set...
+               dev_warn(&intf->dev, "no suspend for driver %s?\n",
+                               driver->name);
+               mark_quiesced(intf);
+       }
+
+done:
+       // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+       if (status == 0)
+               intf->dev.power.power_state.event = msg.event;
+       return status;
+}
+
+/* Caller has locked intf's usb_device's pm_mutex */
+static int resume_interface(struct usb_interface *intf)
+{
+       struct usb_driver       *driver;
+       int                     status = 0;
+
+       if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED ||
+                       is_active(intf))
+               goto done;
+
+       /* Don't let autoresume interfere with unbinding */
+       if (intf->condition == USB_INTERFACE_UNBINDING)
+               goto done;
+
+       /* Can't resume it if it doesn't have a driver. */
+       if (intf->condition == USB_INTERFACE_UNBOUND) {
+               status = -ENOTCONN;
+               goto done;
+       }
+       driver = to_usb_driver(intf->dev.driver);
+
+       if (driver->resume) {
+               status = driver->resume(intf);
+               if (status)
+                       dev_err(&intf->dev, "%s error %d\n",
+                                       "resume", status);
+               else
+                       mark_active(intf);
+       } else {
+               dev_warn(&intf->dev, "no resume for driver %s?\n",
+                               driver->name);
+               mark_active(intf);
+       }
+
+done:
+       // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
+       if (status == 0)
+               intf->dev.power.power_state.event = PM_EVENT_ON;
+       return status;
+}
+
+/**
+ * usb_suspend_both - suspend a USB device and its interfaces
+ * @udev: the usb_device to suspend
+ * @msg: Power Management message describing this state transition
+ *
+ * This is the central routine for suspending USB devices.  It calls the
+ * suspend methods for all the interface drivers in @udev and then calls
+ * the suspend method for @udev itself.  If an error occurs at any stage,
+ * all the interfaces which were suspended are resumed so that they remain
+ * in the same state as the device.
+ *
+ * If an autosuspend is in progress (@udev->auto_pm is set), the routine
+ * checks first to make sure that neither the device itself or any of its
+ * active interfaces is in use (pm_usage_cnt is greater than 0).  If they
+ * are, the autosuspend fails.
+ *
+ * If the suspend succeeds, the routine recursively queues an autosuspend
+ * request for @udev's parent device, thereby propagating the change up
+ * the device tree.  If all of the parent's children are now suspended,
+ * the parent will autosuspend in turn.
+ *
+ * The suspend method calls are subject to mutual exclusion under control
+ * of @udev's pm_mutex.  Many of these calls are also under the protection
+ * of @udev's device lock (including all requests originating outside the
+ * USB subsystem), but autosuspend requests generated by a child device or
+ * interface driver may not be.  Usbcore will insure that the method calls
+ * do not arrive during bind, unbind, or reset operations.  However, drivers
+ * must be prepared to handle suspend calls arriving at unpredictable times.
+ * The only way to block such calls is to do an autoresume (preventing
+ * autosuspends) while holding @udev's device lock (preventing outside
+ * suspends).
+ *
+ * The caller must hold @udev->pm_mutex.
+ *
+ * This routine can run only in process context.
+ */
+int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+{
+       int                     status = 0;
+       int                     i = 0;
+       struct usb_interface    *intf;
+       struct usb_device       *parent = udev->parent;
+
+       cancel_delayed_work(&udev->autosuspend);
+       if (udev->state == USB_STATE_NOTATTACHED)
+               return 0;
+       if (udev->state == USB_STATE_SUSPENDED)
+               return 0;
+
+       udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
+
+       /* For autosuspend, fail fast if anything is in use.
+        * Also fail if any interfaces require remote wakeup but it
+        * isn't available. */
+       if (udev->auto_pm) {
+               if (udev->pm_usage_cnt > 0)
+                       return -EBUSY;
+               if (udev->actconfig) {
+                       for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
+                               intf = udev->actconfig->interface[i];
+                               if (!is_active(intf))
+                                       continue;
+                               if (intf->pm_usage_cnt > 0)
+                                       return -EBUSY;
+                               if (intf->needs_remote_wakeup &&
+                                               !udev->do_remote_wakeup) {
+                                       dev_dbg(&udev->dev,
+       "remote wakeup needed for autosuspend\n");
+                                       return -EOPNOTSUPP;
+                               }
+                       }
+                       i = 0;
+               }
+       }
+
+       /* Suspend all the interfaces and then udev itself */
+       if (udev->actconfig) {
+               for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
+                       intf = udev->actconfig->interface[i];
+                       status = suspend_interface(intf, msg);
+                       if (status != 0)
+                               break;
+               }
+       }
+       if (status == 0)
+               status = suspend_device(udev, msg);
+
+       /* If the suspend failed, resume interfaces that did get suspended */
+       if (status != 0) {
+               while (--i >= 0) {
+                       intf = udev->actconfig->interface[i];
+                       resume_interface(intf);
+               }
+
+       /* If the suspend succeeded, propagate it up the tree */
+       } else if (parent)
+               usb_autosuspend_device(parent, 0);
+
+       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       return status;
+}
+
+/**
+ * usb_resume_both - resume a USB device and its interfaces
+ * @udev: the usb_device to resume
+ *
+ * This is the central routine for resuming USB devices.  It calls the
+ * the resume method for @udev and then calls the resume methods for all
+ * the interface drivers in @udev.
+ *
+ * Before starting the resume, the routine calls itself recursively for
+ * the parent device of @udev, thereby propagating the change up the device
+ * tree and assuring that @udev will be able to resume.  If the parent is
+ * unable to resume successfully, the routine fails.
+ *
+ * The resume method calls are subject to mutual exclusion under control
+ * of @udev's pm_mutex.  Many of these calls are also under the protection
+ * of @udev's device lock (including all requests originating outside the
+ * USB subsystem), but autoresume requests generated by a child device or
+ * interface driver may not be.  Usbcore will insure that the method calls
+ * do not arrive during bind, unbind, or reset operations.  However, drivers
+ * must be prepared to handle resume calls arriving at unpredictable times.
+ * The only way to block such calls is to do an autoresume (preventing
+ * other autoresumes) while holding @udev's device lock (preventing outside
+ * resumes).
+ *
+ * The caller must hold @udev->pm_mutex.
+ *
+ * This routine can run only in process context.
+ */
+int usb_resume_both(struct usb_device *udev)
+{
+       int                     status = 0;
+       int                     i;
+       struct usb_interface    *intf;
+       struct usb_device       *parent = udev->parent;
+
+       cancel_delayed_work(&udev->autosuspend);
+       if (udev->state == USB_STATE_NOTATTACHED)
+               return -ENODEV;
+
+       /* Propagate the resume up the tree, if necessary */
+       if (udev->state == USB_STATE_SUSPENDED) {
+               if (parent) {
+                       mutex_lock_nested(&parent->pm_mutex, parent->level);
+                       parent->auto_pm = 1;
+                       status = usb_resume_both(parent);
+               } else {
+
+                       /* We can't progagate beyond the USB subsystem,
+                        * so if a root hub's controller is suspended
+                        * then we're stuck. */
+                       if (udev->dev.parent->power.power_state.event !=
+                                       PM_EVENT_ON)
+                               status = -EHOSTUNREACH;
+               }
+               if (status == 0)
+                       status = resume_device(udev);
+               if (parent)
+                       mutex_unlock(&parent->pm_mutex);
+       } else {
+
+               /* Needed only for setting udev->dev.power.power_state.event
+                * and for possible debugging message. */
+               status = resume_device(udev);
+       }
+
+       /* Now the parent won't suspend until we are finished */
+
+       if (status == 0 && udev->actconfig) {
+               for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
+                       intf = udev->actconfig->interface[i];
+                       resume_interface(intf);
+               }
+       }
+
+       // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
+       return status;
+}
+
+#ifdef CONFIG_USB_SUSPEND
+
+/**
+ * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
+ * @udev - the usb_device to autosuspend
+ * @dec_usage_cnt - flag to decrement @udev's PM-usage counter
+ *
+ * This routine should be called when a core subsystem is finished using
+ * @udev and wants to allow it to autosuspend.  Examples would be when
+ * @udev's device file in usbfs is closed or after a configuration change.
+ *
+ * @dec_usage_cnt should be 1 if the subsystem previously incremented
+ * @udev's usage counter (such as by passing 1 to usb_autoresume_device);
+ * otherwise it should be 0.
+ *
+ * If the usage counter for @udev or any of its active interfaces is greater
+ * than 0, the autosuspend request will not be queued.  (If an interface
+ * driver does not support autosuspend then its usage counter is permanently
+ * positive.)  Likewise, if an interface driver requires remote-wakeup
+ * capability during autosuspend but remote wakeup is disabled, the
+ * autosuspend will fail.
+ *
+ * Often the caller will hold @udev's device lock, but this is not
+ * necessary.
+ *
+ * This routine can run only in process context.
+ */
+void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
+{
+       mutex_lock_nested(&udev->pm_mutex, udev->level);
+       udev->pm_usage_cnt -= dec_usage_cnt;
+       if (udev->pm_usage_cnt <= 0)
+               schedule_delayed_work(&udev->autosuspend,
+                               USB_AUTOSUSPEND_DELAY);
+       mutex_unlock(&udev->pm_mutex);
+       // dev_dbg(&udev->dev, "%s: cnt %d\n",
+       //              __FUNCTION__, udev->pm_usage_cnt);
+}
+
+/**
+ * usb_autoresume_device - immediately autoresume a USB device and its interfaces
+ * @udev - the usb_device to autoresume
+ * @inc_usage_cnt - flag to increment @udev's PM-usage counter
+ *
+ * This routine should be called when a core subsystem wants to use @udev
+ * and needs to guarantee that it is not suspended.  In addition, the
+ * caller can prevent @udev from being autosuspended subsequently.  (Note
+ * that this will not prevent suspend events originating in the PM core.)
+ * Examples would be when @udev's device file in usbfs is opened (autosuspend
+ * should be prevented until the file is closed) or when a remote-wakeup
+ * request is received (later autosuspends should not be prevented).
+ *
+ * @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent
+ * autosuspends.  This prevention will persist until the usage counter is
+ * decremented again (such as by passing 1 to usb_autosuspend_device).
+ * Otherwise @inc_usage_cnt should be 0 to leave the usage counter unchanged.
+ * Regardless, if the autoresume fails then the usage counter is not
+ * incremented.
+ *
+ * Often the caller will hold @udev's device lock, but this is not
+ * necessary (and attempting it might cause deadlock).
+ *
+ * This routine can run only in process context.
+ */
+int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
+{
+       int     status;
+
+       mutex_lock_nested(&udev->pm_mutex, udev->level);
+       udev->pm_usage_cnt += inc_usage_cnt;
+       udev->auto_pm = 1;
+       status = usb_resume_both(udev);
+       if (status != 0)
+               udev->pm_usage_cnt -= inc_usage_cnt;
+       mutex_unlock(&udev->pm_mutex);
+       // dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
+       //              __FUNCTION__, status, udev->pm_usage_cnt);
+       return status;
+}
+
+/**
+ * usb_autopm_put_interface - decrement a USB interface's PM-usage counter
+ * @intf - the usb_interface whose counter should be decremented
+ *
+ * This routine should be called by an interface driver when it is
+ * finished using @intf and wants to allow it to autosuspend.  A typical
+ * example would be a character-device driver when its device file is
+ * closed.
+ *
+ * The routine decrements @intf's usage counter.  When the counter reaches
+ * 0, a delayed autosuspend request for @intf's device is queued.  When
+ * the delay expires, if @intf->pm_usage_cnt is still <= 0 along with all
+ * the other usage counters for the sibling interfaces and @intf's
+ * usb_device, the device and all its interfaces will be autosuspended.
+ *
+ * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
+ * core will not change its value other than the increment and decrement
+ * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
+ * may use this simple counter-oriented discipline or may set the value
+ * any way it likes.
+ *
+ * If the driver has set @intf->needs_remote_wakeup then autosuspend will
+ * take place only if the device's remote-wakeup facility is enabled.
+ *
+ * Suspend method calls queued by this routine can arrive at any time
+ * while @intf is resumed and its usage counter is equal to 0.  They are
+ * not protected by the usb_device's lock but only by its pm_mutex.
+ * Drivers must provide their own synchronization.
+ *
+ * This routine can run only in process context.
+ */
+void usb_autopm_put_interface(struct usb_interface *intf)
+{
+       struct usb_device       *udev = interface_to_usbdev(intf);
+
+       mutex_lock_nested(&udev->pm_mutex, udev->level);
+       if (intf->condition != USB_INTERFACE_UNBOUND) {
+               if (--intf->pm_usage_cnt <= 0)
+                       schedule_delayed_work(&udev->autosuspend,
+                                       USB_AUTOSUSPEND_DELAY);
+       }
+       mutex_unlock(&udev->pm_mutex);
+       // dev_dbg(&intf->dev, "%s: cnt %d\n",
+       //              __FUNCTION__, intf->pm_usage_cnt);
+}
+EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
+
+/**
+ * usb_autopm_get_interface - increment a USB interface's PM-usage counter
+ * @intf - the usb_interface whose counter should be incremented
+ *
+ * This routine should be called by an interface driver when it wants to
+ * use @intf and needs to guarantee that it is not suspended.  In addition,
+ * the routine prevents @intf from being autosuspended subsequently.  (Note
+ * that this will not prevent suspend events originating in the PM core.)
+ * This prevention will persist until usb_autopm_put_interface() is called
+ * or @intf is unbound.  A typical example would be a character-device
+ * driver when its device file is opened.
+ *
+ * The routine increments @intf's usage counter.  So long as the counter
+ * is greater than 0, autosuspend will not be allowed for @intf or its
+ * usb_device.  When the driver is finished using @intf it should call
+ * usb_autopm_put_interface() to decrement the usage counter and queue
+ * a delayed autosuspend request (if the counter is <= 0).
+ *
+ * Note that @intf->pm_usage_cnt is owned by the interface driver.  The
+ * core will not change its value other than the increment and decrement
+ * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver
+ * may use this simple counter-oriented discipline or may set the value
+ * any way it likes.
+ *
+ * Resume method calls generated by this routine can arrive at any time
+ * while @intf is suspended.  They are not protected by the usb_device's
+ * lock but only by its pm_mutex.  Drivers must provide their own
+ * synchronization.
+ *
+ * This routine can run only in process context.
+ */
+int usb_autopm_get_interface(struct usb_interface *intf)
+{
+       struct usb_device       *udev = interface_to_usbdev(intf);
+       int                     status;
+
+       mutex_lock_nested(&udev->pm_mutex, udev->level);
+       if (intf->condition == USB_INTERFACE_UNBOUND)
+               status = -ENODEV;
+       else {
+               ++intf->pm_usage_cnt;
+               udev->auto_pm = 1;
+               status = usb_resume_both(udev);
+               if (status != 0)
+                       --intf->pm_usage_cnt;
+       }
+       mutex_unlock(&udev->pm_mutex);
+       // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
+       //              __FUNCTION__, status, intf->pm_usage_cnt);
+       return status;
+}
+EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
+
+#endif /* CONFIG_USB_SUSPEND */
+
+static int usb_suspend(struct device *dev, pm_message_t message)
+{
+       int     status;
+
+       if (is_usb_device(dev)) {
+               struct usb_device *udev = to_usb_device(dev);
+
+               mutex_lock_nested(&udev->pm_mutex, udev->level);
+               udev->auto_pm = 0;
+               status = usb_suspend_both(udev, message);
+               mutex_unlock(&udev->pm_mutex);
+       } else
+               status = 0;
+       return status;
+}
+
+static int usb_resume(struct device *dev)
+{
+       int     status;
+
+       if (is_usb_device(dev)) {
+               struct usb_device *udev = to_usb_device(dev);
+
+               mutex_lock_nested(&udev->pm_mutex, udev->level);
+               udev->auto_pm = 0;
+               status = usb_resume_both(udev);
+               mutex_unlock(&udev->pm_mutex);
+
+               /* Rebind drivers that had no suspend method? */
+       } else
+               status = 0;
+       return status;
+}
+
+#endif /* CONFIG_PM */
+
+struct bus_type usb_bus_type = {
+       .name =         "usb",
+       .match =        usb_device_match,
+       .uevent =       usb_uevent,
+#ifdef CONFIG_PM
+       .suspend =      usb_suspend,
+       .resume =       usb_resume,
+#endif
+};
index 247b5a4913a8079491f0104bfe5eaeaf972d8fd1..3ebb90149e93ef7319ae529c22da546032172730 100644 (file)
@@ -207,9 +207,9 @@ static void ep_device_release(struct device *dev)
        kfree(ep_dev);
 }
 
-void usb_create_ep_files(struct device *parent,
-                        struct usb_host_endpoint *endpoint,
-                        struct usb_device *udev)
+int usb_create_ep_files(struct device *parent,
+                       struct usb_host_endpoint *endpoint,
+                       struct usb_device *udev)
 {
        char name[8];
        struct ep_device *ep_dev;
@@ -242,19 +242,33 @@ void usb_create_ep_files(struct device *parent,
        retval = device_register(&ep_dev->dev);
        if (retval)
                goto error;
-       sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+       retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+       if (retval)
+               goto error_group;
 
        endpoint->ep_dev = ep_dev;
 
        /* create the symlink to the old-style "ep_XX" directory */
        sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
-       sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name);
-
+       retval = sysfs_create_link(&parent->kobj,
+                                  &endpoint->ep_dev->dev.kobj, name);
+       if (retval)
+               goto error_link;
 exit:
-       return;
+       return retval;
+
+error_link:
+       sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
+
+error_group:
+       device_unregister(&ep_dev->dev);
+       endpoint->ep_dev = NULL;
+       destroy_endpoint_class();
+       return retval;
 error:
        kfree(ep_dev);
-       return;
+       destroy_endpoint_class();
+       return retval;
 }
 
 void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
index 8de4f8c99d61f3a7cb01696bde29202ed814b160..c376c655c5defc8f6a0693430c29663f6b4e2a44 100644 (file)
@@ -55,7 +55,7 @@ static int usb_open(struct inode * inode, struct file * file)
        return err;
 }
 
-static struct file_operations usb_fops = {
+static const struct file_operations usb_fops = {
        .owner =        THIS_MODULE,
        .open =         usb_open,
 };
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
new file mode 100644 (file)
index 0000000..16332cc
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * drivers/usb/generic.c - generic driver for USB devices (not interfaces)
+ *
+ * (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * based on drivers/usb/usb.c which had the following copyrights:
+ *     (C) Copyright Linus Torvalds 1999
+ *     (C) Copyright Johannes Erdfelt 1999-2001
+ *     (C) Copyright Andreas Gal 1999
+ *     (C) Copyright Gregory P. Smith 1999
+ *     (C) Copyright Deti Fliegl 1999 (new USB architecture)
+ *     (C) Copyright Randy Dunlap 2000
+ *     (C) Copyright David Brownell 2000-2004
+ *     (C) Copyright Yggdrasil Computing, Inc. 2000
+ *             (usb_device_id matching changes by Adam J. Richter)
+ *     (C) Copyright Greg Kroah-Hartman 2002-2003
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/usb.h>
+#include "usb.h"
+
+static inline const char *plural(int n)
+{
+       return (n == 1 ? "" : "s");
+}
+
+static int choose_configuration(struct usb_device *udev)
+{
+       int i;
+       int num_configs;
+       int insufficient_power = 0;
+       struct usb_host_config *c, *best;
+
+       best = NULL;
+       c = udev->config;
+       num_configs = udev->descriptor.bNumConfigurations;
+       for (i = 0; i < num_configs; (i++, c++)) {
+               struct usb_interface_descriptor *desc = NULL;
+
+               /* It's possible that a config has no interfaces! */
+               if (c->desc.bNumInterfaces > 0)
+                       desc = &c->intf_cache[0]->altsetting->desc;
+
+               /*
+                * HP's USB bus-powered keyboard has only one configuration
+                * and it claims to be self-powered; other devices may have
+                * similar errors in their descriptors.  If the next test
+                * were allowed to execute, such configurations would always
+                * be rejected and the devices would not work as expected.
+                * In the meantime, we run the risk of selecting a config
+                * that requires external power at a time when that power
+                * isn't available.  It seems to be the lesser of two evils.
+                *
+                * Bugzilla #6448 reports a device that appears to crash
+                * when it receives a GET_DEVICE_STATUS request!  We don't
+                * have any other way to tell whether a device is self-powered,
+                * but since we don't use that information anywhere but here,
+                * the call has been removed.
+                *
+                * Maybe the GET_DEVICE_STATUS call and the test below can
+                * be reinstated when device firmwares become more reliable.
+                * Don't hold your breath.
+                */
+#if 0
+               /* Rule out self-powered configs for a bus-powered device */
+               if (bus_powered && (c->desc.bmAttributes &
+                                       USB_CONFIG_ATT_SELFPOWER))
+                       continue;
+#endif
+
+               /*
+                * The next test may not be as effective as it should be.
+                * Some hubs have errors in their descriptor, claiming
+                * to be self-powered when they are really bus-powered.
+                * We will overestimate the amount of current such hubs
+                * make available for each port.
+                *
+                * This is a fairly benign sort of failure.  It won't
+                * cause us to reject configurations that we should have
+                * accepted.
+                */
+
+               /* Rule out configs that draw too much bus current */
+               if (c->desc.bMaxPower * 2 > udev->bus_mA) {
+                       insufficient_power++;
+                       continue;
+               }
+
+               /* If the first config's first interface is COMM/2/0xff
+                * (MSFT RNDIS), rule it out unless Linux has host-side
+                * RNDIS support. */
+               if (i == 0 && desc
+                               && desc->bInterfaceClass == USB_CLASS_COMM
+                               && desc->bInterfaceSubClass == 2
+                               && desc->bInterfaceProtocol == 0xff) {
+#ifndef CONFIG_USB_NET_RNDIS_HOST
+                       continue;
+#else
+                       best = c;
+#endif
+               }
+
+               /* From the remaining configs, choose the first one whose
+                * first interface is for a non-vendor-specific class.
+                * Reason: Linux is more likely to have a class driver
+                * than a vendor-specific driver. */
+               else if (udev->descriptor.bDeviceClass !=
+                                               USB_CLASS_VENDOR_SPEC &&
+                               (!desc || desc->bInterfaceClass !=
+                                               USB_CLASS_VENDOR_SPEC)) {
+                       best = c;
+                       break;
+               }
+
+               /* If all the remaining configs are vendor-specific,
+                * choose the first one. */
+               else if (!best)
+                       best = c;
+       }
+
+       if (insufficient_power > 0)
+               dev_info(&udev->dev, "rejected %d configuration%s "
+                       "due to insufficient available bus power\n",
+                       insufficient_power, plural(insufficient_power));
+
+       if (best) {
+               i = best->desc.bConfigurationValue;
+               dev_info(&udev->dev,
+                       "configuration #%d chosen from %d choice%s\n",
+                       i, num_configs, plural(num_configs));
+       } else {
+               i = -1;
+               dev_warn(&udev->dev,
+                       "no configuration chosen from %d choice%s\n",
+                       num_configs, plural(num_configs));
+       }
+       return i;
+}
+
+static int generic_probe(struct usb_device *udev)
+{
+       int err, c;
+
+       /* put device-specific files into sysfs */
+       usb_create_sysfs_dev_files(udev);
+
+       /* Choose and set the configuration.  This registers the interfaces
+        * with the driver core and lets interface drivers bind to them.
+        */
+       c = choose_configuration(udev);
+       if (c >= 0) {
+               err = usb_set_configuration(udev, c);
+               if (err) {
+                       dev_err(&udev->dev, "can't set config #%d, error %d\n",
+                                       c, err);
+                       /* This need not be fatal.  The user can try to
+                        * set other configurations. */
+               }
+       }
+
+       /* USB device state == configured ... usable */
+       usb_notify_add_device(udev);
+
+       return 0;
+}
+
+static void generic_disconnect(struct usb_device *udev)
+{
+       usb_notify_remove_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_remove_sysfs_dev_files(udev);
+}
+
+#ifdef CONFIG_PM
+
+static int generic_suspend(struct usb_device *udev, pm_message_t msg)
+{
+       /* USB devices enter SUSPEND state through their hubs, but can be
+        * marked for FREEZE as soon as their children are already idled.
+        * But those semantics are useless, so we equate the two (sigh).
+        */
+       return usb_port_suspend(udev);
+}
+
+static int generic_resume(struct usb_device *udev)
+{
+       return usb_port_resume(udev);
+}
+
+#endif /* CONFIG_PM */
+
+struct usb_device_driver usb_generic_driver = {
+       .name = "usb",
+       .probe = generic_probe,
+       .disconnect = generic_disconnect,
+#ifdef CONFIG_PM
+       .suspend = generic_suspend,
+       .resume = generic_resume,
+#endif
+       .supports_autosuspend = 1,
+};
index 5078fb3375e34e5c573ef86113b81437ffff1d32..edf4300a3f7a75d748776ab3fe3d69fbf1a6f66d 100644 (file)
@@ -281,7 +281,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
                        (void) usb_hcd_pci_resume (dev);
                }
 
-       } else {
+       } else if (hcd->state != HC_STATE_HALT) {
                dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n",
                        hcd->state);
                WARN_ON(1);
@@ -413,4 +413,20 @@ EXPORT_SYMBOL (usb_hcd_pci_resume);
 
 #endif /* CONFIG_PM */
 
+/**
+ * usb_hcd_pci_shutdown - shutdown host controller
+ * @dev: USB Host Controller being shutdown
+ */
+void usb_hcd_pci_shutdown (struct pci_dev *dev)
+{
+       struct usb_hcd          *hcd;
+
+       hcd = pci_get_drvdata(dev);
+       if (!hcd)
+               return;
+
+       if (hcd->driver->shutdown)
+               hcd->driver->shutdown(hcd);
+}
+EXPORT_SYMBOL (usb_hcd_pci_shutdown);
 
index fb4d058bbde00d006deb8d4f50ce7496fbcf1384..e86f6295708555ea7cd76df5030831f58946f7f3 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/mutex.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
+#include <linux/platform_device.h>
 
 #include <linux/usb.h>
 
@@ -632,31 +633,20 @@ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
 
 /*-------------------------------------------------------------------------*/
 
-/* Asynchronous unlinks of root-hub control URBs are legal, but they
- * don't do anything.  Status URB unlinks must be made in process context
- * with interrupts enabled.
+/* Unlinks of root-hub control URBs are legal, but they don't do anything
+ * since these URBs always execute synchronously.
  */
 static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
 {
-       if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */
-               if (in_interrupt())
-                       return 0;               /* nothing to do */
-
-               spin_lock_irq(&urb->lock);      /* from usb_kill_urb */
-               ++urb->reject;
-               spin_unlock_irq(&urb->lock);
-
-               wait_event(usb_kill_urb_queue,
-                               atomic_read(&urb->use_count) == 0);
+       unsigned long   flags;
 
-               spin_lock_irq(&urb->lock);
-               --urb->reject;
-               spin_unlock_irq(&urb->lock);
+       if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */
+               ;       /* Do nothing */
 
        } else {                                /* Status URB */
                if (!hcd->uses_new_polling)
-                       del_timer_sync (&hcd->rh_timer);
-               local_irq_disable ();
+                       del_timer (&hcd->rh_timer);
+               local_irq_save (flags);
                spin_lock (&hcd_root_hub_lock);
                if (urb == hcd->status_urb) {
                        hcd->status_urb = NULL;
@@ -666,7 +656,7 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
                spin_unlock (&hcd_root_hub_lock);
                if (urb)
                        usb_hcd_giveback_urb (hcd, urb, NULL);
-               local_irq_enable ();
+               local_irq_restore (flags);
        }
 
        return 0;
@@ -674,31 +664,6 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
 
 /*-------------------------------------------------------------------------*/
 
-/* exported only within usbcore */
-struct usb_bus *usb_bus_get(struct usb_bus *bus)
-{
-       if (bus)
-               kref_get(&bus->kref);
-       return bus;
-}
-
-static void usb_host_release(struct kref *kref)
-{
-       struct usb_bus *bus = container_of(kref, struct usb_bus, kref);
-
-       if (bus->release)
-               bus->release(bus);
-}
-
-/* exported only within usbcore */
-void usb_bus_put(struct usb_bus *bus)
-{
-       if (bus)
-               kref_put(&bus->kref, usb_host_release);
-}
-
-/*-------------------------------------------------------------------------*/
-
 static struct class *usb_host_class;
 
 int usb_host_init(void)
@@ -730,39 +695,12 @@ static void usb_bus_init (struct usb_bus *bus)
        bus->devnum_next = 1;
 
        bus->root_hub = NULL;
-       bus->hcpriv = NULL;
        bus->busnum = -1;
        bus->bandwidth_allocated = 0;
        bus->bandwidth_int_reqs  = 0;
        bus->bandwidth_isoc_reqs = 0;
 
        INIT_LIST_HEAD (&bus->bus_list);
-
-       kref_init(&bus->kref);
-}
-
-/**
- * usb_alloc_bus - creates a new USB host controller structure
- * @op: pointer to a struct usb_operations that this bus structure should use
- * Context: !in_interrupt()
- *
- * Creates a USB host controller bus structure with the specified 
- * usb_operations and initializes all the necessary internal objects.
- *
- * If no memory is available, NULL is returned.
- *
- * The caller should call usb_put_bus() when it is finished with the structure.
- */
-struct usb_bus *usb_alloc_bus (struct usb_operations *op)
-{
-       struct usb_bus *bus;
-
-       bus = kzalloc (sizeof *bus, GFP_KERNEL);
-       if (!bus)
-               return NULL;
-       usb_bus_init (bus);
-       bus->op = op;
-       return bus;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1112,10 +1050,10 @@ static void urb_unlink (struct urb *urb)
  * expects usb_submit_urb() to have sanity checked and conditioned all
  * inputs in the urb
  */
-static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
+int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
 {
        int                     status;
-       struct usb_hcd          *hcd = urb->dev->bus->hcpriv;
+       struct usb_hcd          *hcd = bus_to_hcd(urb->dev->bus);
        struct usb_host_endpoint *ep;
        unsigned long           flags;
 
@@ -1186,7 +1124,7 @@ doit:
        /* lower level hcd code should use *_dma exclusively,
         * unless it uses pio or talks to another transport.
         */
-       if (hcd->self.controller->dma_mask) {
+       if (hcd->self.uses_dma) {
                if (usb_pipecontrol (urb->pipe)
                        && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
                        urb->setup_dma = dma_map_single (
@@ -1221,9 +1159,10 @@ done:
 /*-------------------------------------------------------------------------*/
 
 /* called in any context */
-static int hcd_get_frame_number (struct usb_device *udev)
+int usb_hcd_get_frame_number (struct usb_device *udev)
 {
-       struct usb_hcd  *hcd = (struct usb_hcd *)udev->bus->hcpriv;
+       struct usb_hcd  *hcd = bus_to_hcd(udev->bus);
+
        if (!HC_IS_RUNNING (hcd->state))
                return -ESHUTDOWN;
        return hcd->driver->get_frame_number (hcd);
@@ -1263,7 +1202,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
  * caller guarantees urb won't be recycled till both unlink()
  * and the urb's completion function return
  */
-static int hcd_unlink_urb (struct urb *urb, int status)
+int usb_hcd_unlink_urb (struct urb *urb, int status)
 {
        struct usb_host_endpoint        *ep;
        struct usb_hcd                  *hcd = NULL;
@@ -1296,7 +1235,7 @@ static int hcd_unlink_urb (struct urb *urb, int status)
        spin_lock (&hcd_data_lock);
 
        sys = &urb->dev->dev;
-       hcd = urb->dev->bus->hcpriv;
+       hcd = bus_to_hcd(urb->dev->bus);
        if (hcd == NULL) {
                retval = -ENODEV;
                goto done;
@@ -1354,41 +1293,33 @@ done:
 /*-------------------------------------------------------------------------*/
 
 /* disables the endpoint: cancels any pending urbs, then synchronizes with
- * the hcd to make sure all endpoint state is gone from hardware. use for
+ * the hcd to make sure all endpoint state is gone from hardware, and then
+ * waits until the endpoint's queue is completely drained. use for
  * set_configuration, set_interface, driver removal, physical disconnect.
  *
  * example:  a qh stored in ep->hcpriv, holding state related to endpoint
  * type, maxpacket size, toggle, halt status, and scheduling.
  */
-static void
-hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
+void usb_hcd_endpoint_disable (struct usb_device *udev,
+               struct usb_host_endpoint *ep)
 {
        struct usb_hcd          *hcd;
        struct urb              *urb;
 
-       hcd = udev->bus->hcpriv;
+       hcd = bus_to_hcd(udev->bus);
 
        WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT &&
                        udev->state != USB_STATE_NOTATTACHED);
 
        local_irq_disable ();
 
-       /* FIXME move most of this into message.c as part of its
-        * endpoint disable logic
-        */
-
        /* ep is already gone from udev->ep_{in,out}[]; no more submits */
 rescan:
        spin_lock (&hcd_data_lock);
        list_for_each_entry (urb, &ep->urb_list, urb_list) {
                int     tmp;
 
-               /* another cpu may be in hcd, spinning on hcd_data_lock
-                * to giveback() this urb.  the races here should be
-                * small, but a full fix needs a new "can't submit"
-                * urb state.
-                * FIXME urb->reject should allow that...
-                */
+               /* the urb may already have been unlinked */
                if (urb->status != -EINPROGRESS)
                        continue;
                usb_get_urb (urb);
@@ -1430,6 +1361,30 @@ rescan:
        might_sleep ();
        if (hcd->driver->endpoint_disable)
                hcd->driver->endpoint_disable (hcd, ep);
+
+       /* Wait until the endpoint queue is completely empty.  Most HCDs
+        * will have done this already in their endpoint_disable method,
+        * but some might not.  And there could be root-hub control URBs
+        * still pending since they aren't affected by the HCDs'
+        * endpoint_disable methods.
+        */
+       while (!list_empty (&ep->urb_list)) {
+               spin_lock_irq (&hcd_data_lock);
+
+               /* The list may have changed while we acquired the spinlock */
+               urb = NULL;
+               if (!list_empty (&ep->urb_list)) {
+                       urb = list_entry (ep->urb_list.prev, struct urb,
+                                       urb_list);
+                       usb_get_urb (urb);
+               }
+               spin_unlock_irq (&hcd_data_lock);
+
+               if (urb) {
+                       usb_kill_urb (urb);
+                       usb_put_urb (urb);
+               }
+       }
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1476,50 +1431,6 @@ int hcd_bus_resume (struct usb_bus *bus)
        return status;
 }
 
-/*
- * usb_hcd_suspend_root_hub - HCD autosuspends downstream ports
- * @hcd: host controller for this root hub
- *
- * This call arranges that usb_hcd_resume_root_hub() is safe to call later;
- * that the HCD's root hub polling is deactivated; and that the root's hub
- * driver is suspended.  HCDs may call this to autosuspend when their root
- * hub's downstream ports are all inactive:  unpowered, disconnected,
- * disabled, or suspended.
- *
- * The HCD will autoresume on device connect change detection (using SRP
- * or a D+/D- pullup).  The HCD also autoresumes on remote wakeup signaling
- * from any ports that are suspended (if that is enabled).  In most cases,
- * overcurrent signaling (on powered ports) will also start autoresume.
- *
- * Always called with IRQs blocked.
- */
-void usb_hcd_suspend_root_hub (struct usb_hcd *hcd)
-{
-       struct urb      *urb;
-
-       spin_lock (&hcd_root_hub_lock);
-       usb_suspend_root_hub (hcd->self.root_hub);
-
-       /* force status urb to complete/unlink while suspended */
-       if (hcd->status_urb) {
-               urb = hcd->status_urb;
-               urb->status = -ECONNRESET;
-               urb->hcpriv = NULL;
-               urb->actual_length = 0;
-
-               del_timer (&hcd->rh_timer);
-               hcd->poll_pending = 0;
-               hcd->status_urb = NULL;
-       } else
-               urb = NULL;
-       spin_unlock (&hcd_root_hub_lock);
-       hcd->state = HC_STATE_SUSPENDED;
-
-       if (urb)
-               usb_hcd_giveback_urb (hcd, urb, NULL);
-}
-EXPORT_SYMBOL_GPL(usb_hcd_suspend_root_hub);
-
 /**
  * usb_hcd_resume_root_hub - called by HCD to resume its root hub 
  * @hcd: host controller for this root hub
@@ -1583,20 +1494,6 @@ EXPORT_SYMBOL (usb_bus_start_enum);
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue)
- */
-static struct usb_operations usb_hcd_operations = {
-       .get_frame_number =     hcd_get_frame_number,
-       .submit_urb =           hcd_submit_urb,
-       .unlink_urb =           hcd_unlink_urb,
-       .buffer_alloc =         hcd_buffer_alloc,
-       .buffer_free =          hcd_buffer_free,
-       .disable =              hcd_endpoint_disable,
-};
-
-/*-------------------------------------------------------------------------*/
-
 /**
  * usb_hcd_giveback_urb - return URB from HCD to device driver
  * @hcd: host controller returning the URB
@@ -1617,8 +1514,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs
        at_root_hub = (urb->dev == hcd->self.root_hub);
        urb_unlink (urb);
 
-       /* lower level hcd code should use *_dma exclusively */
-       if (hcd->self.controller->dma_mask && !at_root_hub) {
+       /* lower level hcd code should use *_dma exclusively if the
+        * host controller does DMA */
+       if (hcd->self.uses_dma && !at_root_hub) {
                if (usb_pipecontrol (urb->pipe)
                        && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
                        dma_unmap_single (hcd->self.controller, urb->setup_dma,
@@ -1704,14 +1602,6 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
 
 /*-------------------------------------------------------------------------*/
 
-static void hcd_release (struct usb_bus *bus)
-{
-       struct usb_hcd *hcd;
-
-       hcd = container_of(bus, struct usb_hcd, self);
-       kfree(hcd);
-}
-
 /**
  * usb_create_hcd - create and initialize an HCD structure
  * @driver: HC driver that will use this hcd
@@ -1736,13 +1626,12 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
                return NULL;
        }
        dev_set_drvdata(dev, hcd);
+       kref_init(&hcd->kref);
 
        usb_bus_init(&hcd->self);
-       hcd->self.op = &usb_hcd_operations;
-       hcd->self.hcpriv = hcd;
-       hcd->self.release = &hcd_release;
        hcd->self.controller = dev;
        hcd->self.bus_name = bus_name;
+       hcd->self.uses_dma = (dev->dma_mask != NULL);
 
        init_timer(&hcd->rh_timer);
        hcd->rh_timer.function = rh_timer_func;
@@ -1756,10 +1645,25 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
 }
 EXPORT_SYMBOL (usb_create_hcd);
 
+static void hcd_release (struct kref *kref)
+{
+       struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
+
+       kfree(hcd);
+}
+
+struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd)
+{
+       if (hcd)
+               kref_get (&hcd->kref);
+       return hcd;
+}
+EXPORT_SYMBOL (usb_get_hcd);
+
 void usb_put_hcd (struct usb_hcd *hcd)
 {
-       dev_set_drvdata(hcd->self.controller, NULL);
-       usb_bus_put(&hcd->self);
+       if (hcd)
+               kref_put (&hcd->kref, hcd_release);
 }
 EXPORT_SYMBOL (usb_put_hcd);
 
@@ -1915,6 +1819,16 @@ void usb_remove_hcd(struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL (usb_remove_hcd);
 
+void
+usb_hcd_platform_shutdown(struct platform_device* dev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(dev);
+
+       if (hcd->driver->shutdown)
+               hcd->driver->shutdown(hcd);
+}
+EXPORT_SYMBOL (usb_hcd_platform_shutdown);
+
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_USB_MON)
index 7022aafb2ae8bedf9460d5c433fcea9329814251..676877c15f8187731e833bab4750407ce1c0bdd2 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
-struct usb_hcd {       /* usb_bus.hcpriv points to this */
+struct usb_hcd {
 
        /*
         * housekeeping
         */
        struct usb_bus          self;           /* hcd is-a bus */
+       struct kref             kref;           /* reference counter */
 
        const char              *product_desc;  /* product/vendor string */
        char                    irq_descr[24];  /* driver + bus # */
@@ -85,6 +86,7 @@ struct usb_hcd {      /* usb_bus.hcpriv points to this */
        unsigned                uses_new_polling:1;
        unsigned                poll_rh:1;      /* poll for rh status? */
        unsigned                poll_pending:1; /* status has changed? */
+       unsigned                wireless:1;     /* Wireless USB HCD */
 
        int                     irq;            /* irq allocated */
        void __iomem            *regs;          /* device memory/io */
@@ -128,8 +130,10 @@ static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
        return &hcd->self;
 }
 
-
-// urb.hcpriv is really hardware-specific
+static inline struct usb_hcd *bus_to_hcd (struct usb_bus *bus)
+{
+       return container_of(bus, struct usb_hcd, self);
+}
 
 struct hcd_timeout {   /* timeouts we allocate */
        struct list_head        timeout_list;
@@ -138,28 +142,6 @@ struct hcd_timeout {       /* timeouts we allocate */
 
 /*-------------------------------------------------------------------------*/
 
-/*
- * FIXME usb_operations should vanish or become hc_driver,
- * when usb_bus and usb_hcd become the same thing.
- */
-
-struct usb_operations {
-       int (*get_frame_number) (struct usb_device *usb_dev);
-       int (*submit_urb) (struct urb *urb, gfp_t mem_flags);
-       int (*unlink_urb) (struct urb *urb, int status);
-
-       /* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
-       void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
-                       gfp_t mem_flags,
-                       dma_addr_t *dma);
-       void (*buffer_free)(struct usb_bus *bus, size_t size,
-                       void *addr, dma_addr_t dma);
-
-       void (*disable)(struct usb_device *udev,
-                       struct usb_host_endpoint *ep);
-};
-
-/* each driver provides one of these, and hardware init support */
 
 struct pt_regs;
 
@@ -192,6 +174,9 @@ struct hc_driver {
        /* cleanly make HCD stop writing memory and doing I/O */
        void    (*stop) (struct usb_hcd *hcd);
 
+       /* shutdown HCD */
+       void    (*shutdown) (struct usb_hcd *hcd);
+
        /* return current frame number */
        int     (*get_frame_number) (struct usb_hcd *hcd);
 
@@ -218,15 +203,25 @@ struct hc_driver {
                /* Needed only if port-change IRQs are level-triggered */
 };
 
-extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
+extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
+extern int usb_hcd_unlink_urb (struct urb *urb, int status);
+extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb,
+               struct pt_regs *regs);
+extern void usb_hcd_endpoint_disable (struct usb_device *udev,
+               struct usb_host_endpoint *ep);
+extern int usb_hcd_get_frame_number (struct usb_device *udev);
 
 extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
                struct device *dev, char *bus_name);
+extern struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd);
 extern void usb_put_hcd (struct usb_hcd *hcd);
 extern int usb_add_hcd(struct usb_hcd *hcd,
                unsigned int irqnum, unsigned long irqflags);
 extern void usb_remove_hcd(struct usb_hcd *hcd);
 
+struct platform_device;
+extern void usb_hcd_platform_shutdown(struct platform_device* dev);
+
 #ifdef CONFIG_PCI
 struct pci_dev;
 struct pci_device_id;
@@ -239,6 +234,8 @@ extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state);
 extern int usb_hcd_pci_resume (struct pci_dev *dev);
 #endif /* CONFIG_PM */
 
+extern void usb_hcd_pci_shutdown (struct pci_dev *dev);
+
 #endif /* CONFIG_PCI */
 
 /* pci-ish (pdev null is ok) buffer alloc/mapping support */
@@ -352,8 +349,6 @@ extern long usb_calc_bus_time (int speed, int is_input,
 
 /*-------------------------------------------------------------------------*/
 
-extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
-
 extern void usb_set_device_state(struct usb_device *udev,
                enum usb_device_state new_state);
 
@@ -365,9 +360,6 @@ extern struct list_head usb_bus_list;
 extern struct mutex usb_bus_list_lock;
 extern wait_queue_head_t usb_kill_urb_queue;
 
-extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
-extern void usb_bus_put (struct usb_bus *bus);
-
 extern void usb_enable_root_hub_irq (struct usb_bus *bus);
 
 extern int usb_find_interface_driver (struct usb_device *dev,
@@ -376,17 +368,11 @@ extern int usb_find_interface_driver (struct usb_device *dev,
 #define usb_endpoint_out(ep_dir)       (!((ep_dir) & USB_DIR_IN))
 
 #ifdef CONFIG_PM
-extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
 extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
 extern void usb_root_hub_lost_power (struct usb_device *rhdev);
 extern int hcd_bus_suspend (struct usb_bus *bus);
 extern int hcd_bus_resume (struct usb_bus *bus);
 #else
-static inline void usb_hcd_suspend_root_hub(struct usb_hcd *hcd)
-{
-       return;
-}
-
 static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
 {
        return;
index 26c8cb5f3e6722467379204762fb5d8a89b938a0..2a8cb3c2b19ca51db6f6aa521cebaca9a84bd58c 100644 (file)
@@ -293,7 +293,7 @@ void usb_kick_khubd(struct usb_device *hdev)
 /* completion function, fires on port status changes and various faults */
 static void hub_irq(struct urb *urb, struct pt_regs *regs)
 {
-       struct usb_hub *hub = (struct usb_hub *)urb->context;
+       struct usb_hub *hub = urb->context;
        int status;
        int i;
        unsigned long bits;
@@ -311,7 +311,7 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs)
                        goto resubmit;
                hub->error = urb->status;
                /* FALL THROUGH */
-       
+
        /* let khubd handle things */
        case 0:                 /* we got data:  port status changed */
                bits = 0;
@@ -452,18 +452,14 @@ static void hub_power_on(struct usb_hub *hub)
        msleep(max(pgood_delay, (unsigned) 100));
 }
 
-static inline void __hub_quiesce(struct usb_hub *hub)
+static void hub_quiesce(struct usb_hub *hub)
 {
        /* (nonblocking) khubd and related activity won't re-trigger */
        hub->quiescing = 1;
        hub->activating = 0;
        hub->resume_root_hub = 0;
-}
 
-static void hub_quiesce(struct usb_hub *hub)
-{
        /* (blocking) stop khubd and related activity */
-       __hub_quiesce(hub);
        usb_kill_urb(hub->urb);
        if (hub->has_indicators)
                cancel_delayed_work(&hub->leds);
@@ -868,13 +864,8 @@ descriptor_error:
 
        endpoint = &desc->endpoint[0].desc;
 
-       /* Output endpoint? Curiouser and curiouser.. */
-       if (!(endpoint->bEndpointAddress & USB_DIR_IN))
-               goto descriptor_error;
-
-       /* If it's not an interrupt endpoint, we'd better punt! */
-       if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                       != USB_ENDPOINT_XFER_INT)
+       /* If it's not an interrupt in endpoint, we'd better punt! */
+       if (!usb_endpoint_is_int_in(endpoint))
                goto descriptor_error;
 
        /* We found a hub */
@@ -1022,26 +1013,29 @@ void usb_set_device_state(struct usb_device *udev,
        if (udev->state == USB_STATE_NOTATTACHED)
                ;       /* do nothing */
        else if (new_state != USB_STATE_NOTATTACHED) {
-               udev->state = new_state;
 
                /* root hub wakeup capabilities are managed out-of-band
                 * and may involve silicon errata ... ignore them here.
                 */
                if (udev->parent) {
-                       if (new_state == USB_STATE_CONFIGURED)
+                       if (udev->state == USB_STATE_SUSPENDED
+                                       || new_state == USB_STATE_SUSPENDED)
+                               ;       /* No change to wakeup settings */
+                       else if (new_state == USB_STATE_CONFIGURED)
                                device_init_wakeup(&udev->dev,
                                        (udev->actconfig->desc.bmAttributes
                                         & USB_CONFIG_ATT_WAKEUP));
-                       else if (new_state != USB_STATE_SUSPENDED)
+                       else
                                device_init_wakeup(&udev->dev, 0);
                }
+               udev->state = new_state;
        } else
                recursively_mark_NOTATTACHED(udev);
        spin_unlock_irqrestore(&device_state_lock, flags);
 }
 
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM
 
 /**
  * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power
@@ -1059,6 +1053,12 @@ void usb_root_hub_lost_power(struct usb_device *rhdev)
        unsigned long flags;
 
        dev_warn(&rhdev->dev, "root hub lost power or was reset\n");
+
+       /* Make sure no potential wakeup events get lost,
+        * by forcing the root hub to be resumed.
+        */
+       rhdev->dev.power.prev_state.event = PM_EVENT_ON;
+
        spin_lock_irqsave(&device_state_lock, flags);
        hub = hdev_to_hub(rhdev);
        for (port1 = 1; port1 <= rhdev->maxchild; ++port1) {
@@ -1072,7 +1072,7 @@ void usb_root_hub_lost_power(struct usb_device *rhdev)
 }
 EXPORT_SYMBOL_GPL(usb_root_hub_lost_power);
 
-#endif
+#endif /* CONFIG_PM */
 
 static void choose_address(struct usb_device *udev)
 {
@@ -1148,144 +1148,28 @@ void usb_disconnect(struct usb_device **pdev)
         * cleaning up all state associated with the current configuration
         * so that the hardware is now fully quiesced.
         */
+       dev_dbg (&udev->dev, "unregistering device\n");
        usb_disable_device(udev, 0);
 
-       usb_notify_remove_device(udev);
+       usb_unlock_device(udev);
 
-       /* Free the device number, remove the /proc/bus/usb entry and
-        * the sysfs attributes, and delete the parent's children[]
+       /* Unregister the device.  The device driver is responsible
+        * for removing the device files from usbfs and sysfs and for
+        * de-configuring the device.
+        */
+       device_del(&udev->dev);
+
+       /* Free the device number and delete the parent's children[]
         * (or root_hub) pointer.
         */
-       dev_dbg (&udev->dev, "unregistering device\n");
        release_address(udev);
-       usb_remove_sysfs_dev_files(udev);
 
        /* Avoid races with recursively_mark_NOTATTACHED() */
        spin_lock_irq(&device_state_lock);
        *pdev = NULL;
        spin_unlock_irq(&device_state_lock);
 
-       usb_unlock_device(udev);
-
-       device_unregister(&udev->dev);
-}
-
-static inline const char *plural(int n)
-{
-       return (n == 1 ? "" : "s");
-}
-
-static int choose_configuration(struct usb_device *udev)
-{
-       int i;
-       int num_configs;
-       int insufficient_power = 0;
-       struct usb_host_config *c, *best;
-
-       best = NULL;
-       c = udev->config;
-       num_configs = udev->descriptor.bNumConfigurations;
-       for (i = 0; i < num_configs; (i++, c++)) {
-               struct usb_interface_descriptor *desc = NULL;
-
-               /* It's possible that a config has no interfaces! */
-               if (c->desc.bNumInterfaces > 0)
-                       desc = &c->intf_cache[0]->altsetting->desc;
-
-               /*
-                * HP's USB bus-powered keyboard has only one configuration
-                * and it claims to be self-powered; other devices may have
-                * similar errors in their descriptors.  If the next test
-                * were allowed to execute, such configurations would always
-                * be rejected and the devices would not work as expected.
-                * In the meantime, we run the risk of selecting a config
-                * that requires external power at a time when that power
-                * isn't available.  It seems to be the lesser of two evils.
-                *
-                * Bugzilla #6448 reports a device that appears to crash
-                * when it receives a GET_DEVICE_STATUS request!  We don't
-                * have any other way to tell whether a device is self-powered,
-                * but since we don't use that information anywhere but here,
-                * the call has been removed.
-                *
-                * Maybe the GET_DEVICE_STATUS call and the test below can
-                * be reinstated when device firmwares become more reliable.
-                * Don't hold your breath.
-                */
-#if 0
-               /* Rule out self-powered configs for a bus-powered device */
-               if (bus_powered && (c->desc.bmAttributes &
-                                       USB_CONFIG_ATT_SELFPOWER))
-                       continue;
-#endif
-
-               /*
-                * The next test may not be as effective as it should be.
-                * Some hubs have errors in their descriptor, claiming
-                * to be self-powered when they are really bus-powered.
-                * We will overestimate the amount of current such hubs
-                * make available for each port.
-                *
-                * This is a fairly benign sort of failure.  It won't
-                * cause us to reject configurations that we should have
-                * accepted.
-                */
-
-               /* Rule out configs that draw too much bus current */
-               if (c->desc.bMaxPower * 2 > udev->bus_mA) {
-                       insufficient_power++;
-                       continue;
-               }
-
-               /* If the first config's first interface is COMM/2/0xff
-                * (MSFT RNDIS), rule it out unless Linux has host-side
-                * RNDIS support. */
-               if (i == 0 && desc
-                               && desc->bInterfaceClass == USB_CLASS_COMM
-                               && desc->bInterfaceSubClass == 2
-                               && desc->bInterfaceProtocol == 0xff) {
-#ifndef CONFIG_USB_NET_RNDIS_HOST
-                       continue;
-#else
-                       best = c;
-#endif
-               }
-
-               /* From the remaining configs, choose the first one whose
-                * first interface is for a non-vendor-specific class.
-                * Reason: Linux is more likely to have a class driver
-                * than a vendor-specific driver. */
-               else if (udev->descriptor.bDeviceClass !=
-                                               USB_CLASS_VENDOR_SPEC &&
-                               (!desc || desc->bInterfaceClass !=
-                                               USB_CLASS_VENDOR_SPEC)) {
-                       best = c;
-                       break;
-               }
-
-               /* If all the remaining configs are vendor-specific,
-                * choose the first one. */
-               else if (!best)
-                       best = c;
-       }
-
-       if (insufficient_power > 0)
-               dev_info(&udev->dev, "rejected %d configuration%s "
-                       "due to insufficient available bus power\n",
-                       insufficient_power, plural(insufficient_power));
-
-       if (best) {
-               i = best->desc.bConfigurationValue;
-               dev_info(&udev->dev,
-                       "configuration #%d chosen from %d choice%s\n",
-                       i, num_configs, plural(num_configs));
-       } else {
-               i = -1;
-               dev_warn(&udev->dev,
-                       "no configuration chosen from %d choice%s\n",
-                       num_configs, plural(num_configs));
-       }
-       return i;
+       put_device(&udev->dev);
 }
 
 #ifdef DEBUG
@@ -1328,7 +1212,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
 int usb_new_device(struct usb_device *udev)
 {
        int err;
-       int c;
 
        err = usb_get_configuration(udev);
        if (err < 0) {
@@ -1371,8 +1254,7 @@ int usb_new_device(struct usb_device *udev)
                                        USB_DT_OTG, (void **) &desc) == 0) {
                        if (desc->bmAttributes & USB_OTG_HNP) {
                                unsigned                port1 = udev->portnum;
-                               struct usb_device       *root = udev->parent;
-                               
+
                                dev_info(&udev->dev,
                                        "Dual-Role OTG device on %sHNP port\n",
                                        (port1 == bus->otg_port)
@@ -1407,9 +1289,9 @@ int usb_new_device(struct usb_device *udev)
                 * (Includes HNP test device.)
                 */
                if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
-                       static int __usb_suspend_device(struct usb_device *,
+                       static int __usb_port_suspend(struct usb_device *,
                                                int port1);
-                       err = __usb_suspend_device(udev, udev->bus->otg_port);
+                       err = __usb_port_suspend(udev, udev->bus->otg_port);
                        if (err < 0)
                                dev_dbg(&udev->dev, "HNP fail, %d\n", err);
                }
@@ -1418,34 +1300,15 @@ int usb_new_device(struct usb_device *udev)
        }
 #endif
 
-       /* put device-specific files into sysfs */
+       /* Register the device.  The device driver is responsible
+        * for adding the device files to usbfs and sysfs and for
+        * configuring the device.
+        */
        err = device_add (&udev->dev);
        if (err) {
                dev_err(&udev->dev, "can't device_add, error %d\n", err);
                goto fail;
        }
-       usb_create_sysfs_dev_files (udev);
-
-       usb_lock_device(udev);
-
-       /* choose and set the configuration. that registers the interfaces
-        * with the driver core, and lets usb device drivers bind to them.
-        */
-       c = choose_configuration(udev);
-       if (c >= 0) {
-               err = usb_set_configuration(udev, c);
-               if (err) {
-                       dev_err(&udev->dev, "can't set config #%d, error %d\n",
-                                       c, err);
-                       /* This need not be fatal.  The user can try to
-                        * set other configurations. */
-               }
-       }
-
-       /* USB device state == configured ... usable */
-       usb_notify_add_device(udev);
-
-       usb_unlock_device(udev);
 
        return 0;
 
@@ -1472,6 +1335,18 @@ static int hub_port_status(struct usb_hub *hub, int port1,
        return ret;
 }
 
+
+/* Returns 1 if @hub is a WUSB root hub, 0 otherwise */
+static unsigned hub_is_wusb(struct usb_hub *hub)
+{
+       struct usb_hcd *hcd;
+       if (hub->hdev->parent != NULL)  /* not a root hub? */
+               return 0;
+       hcd = container_of(hub->hdev->bus, struct usb_hcd, self);
+       return hcd->wireless;
+}
+
+
 #define PORT_RESET_TRIES       5
 #define SET_ADDRESS_TRIES      2
 #define GET_DESCRIPTOR_TRIES   2
@@ -1512,7 +1387,9 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
                /* if we`ve finished resetting, then break out of the loop */
                if (!(portstatus & USB_PORT_STAT_RESET) &&
                    (portstatus & USB_PORT_STAT_ENABLE)) {
-                       if (portstatus & USB_PORT_STAT_HIGH_SPEED)
+                       if (hub_is_wusb(hub))
+                               udev->speed = USB_SPEED_VARIABLE;
+                       else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
                                udev->speed = USB_SPEED_HIGH;
                        else if (portstatus & USB_PORT_STAT_LOW_SPEED)
                                udev->speed = USB_SPEED_LOW;
@@ -1607,6 +1484,7 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
        kick_khubd(hub);
 }
 
+#ifdef CONFIG_PM
 
 #ifdef CONFIG_USB_SUSPEND
 
@@ -1633,7 +1511,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
         * NOTE:  OTG devices may issue remote wakeup (or SRP) even when
         * we don't explicitly enable it here.
         */
-       if (device_may_wakeup(&udev->dev)) {
+       if (udev->do_remote_wakeup) {
                status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
                                USB_DEVICE_REMOTE_WAKEUP, 0,
@@ -1659,7 +1537,8 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
                                USB_CTRL_SET_TIMEOUT);
        } else {
                /* device has up to 10 msec to fully suspend */
-               dev_dbg(&udev->dev, "usb suspend\n");
+               dev_dbg(&udev->dev, "usb %ssuspend\n",
+                               udev->auto_pm ? "auto-" : "");
                usb_set_device_state(udev, USB_STATE_SUSPENDED);
                msleep(10);
        }
@@ -1684,7 +1563,7 @@ static int hub_port_suspend(struct usb_hub *hub, int port1,
  * the root hub for their bus goes into global suspend ... so we don't
  * (falsely) update the device power state to say it suspended.
  */
-static int __usb_suspend_device (struct usb_device *udev, int port1)
+static int __usb_port_suspend (struct usb_device *udev, int port1)
 {
        int     status = 0;
 
@@ -1692,49 +1571,29 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
        if (port1 < 0)
                return port1;
 
-       if (udev->state == USB_STATE_SUSPENDED
-                       || udev->state == USB_STATE_NOTATTACHED) {
-               return 0;
-       }
-
-       /* all interfaces must already be suspended */
-       if (udev->actconfig) {
-               int     i;
-
-               for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-                       struct usb_interface    *intf;
-
-                       intf = udev->actconfig->interface[i];
-                       if (is_active(intf)) {
-                               dev_dbg(&intf->dev, "nyet suspended\n");
-                               return -EBUSY;
-                       }
-               }
-       }
-
-       /* we only change a device's upstream USB link.
-        * root hubs have no upstream USB link.
+       /* we change the device's upstream USB link,
+        * but root hubs have no upstream USB link.
         */
        if (udev->parent)
                status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
                                udev);
-
-       if (status == 0)
-               udev->dev.power.power_state = PMSG_SUSPEND;
+       else {
+               dev_dbg(&udev->dev, "usb %ssuspend\n",
+                               udev->auto_pm ? "auto-" : "");
+               usb_set_device_state(udev, USB_STATE_SUSPENDED);
+       }
        return status;
 }
 
-#endif
-
 /*
- * usb_suspend_device - suspend a usb device
+ * usb_port_suspend - suspend a usb device's upstream port
  * @udev: device that's no longer in active use
  * Context: must be able to sleep; device not locked; pm locks held
  *
  * Suspends a USB device that isn't in active use, conserving power.
  * Devices may wake out of a suspend, if anything important happens,
  * using the remote wakeup mechanism.  They may also be taken out of
- * suspend by the host, using usb_resume_device().  It's also routine
+ * suspend by the host, using usb_port_resume().  It's also routine
  * to disconnect devices while they are suspended.
  *
  * This only affects the USB hardware for a device; its interfaces
@@ -1746,17 +1605,9 @@ static int __usb_suspend_device (struct usb_device *udev, int port1)
  *
  * Returns 0 on success, else negative errno.
  */
-int usb_suspend_device(struct usb_device *udev)
+int usb_port_suspend(struct usb_device *udev)
 {
-#ifdef CONFIG_USB_SUSPEND
-       if (udev->state == USB_STATE_NOTATTACHED)
-               return -ENODEV;
-       return __usb_suspend_device(udev, udev->portnum);
-#else
-       /* NOTE:  udev->state unchanged, it's not lying ... */
-       udev->dev.power.power_state = PMSG_SUSPEND;
-       return 0;
-#endif
+       return __usb_port_suspend(udev, udev->portnum);
 }
 
 /*
@@ -1767,7 +1618,7 @@ int usb_suspend_device(struct usb_device *udev)
  * resume (by host) or remote wakeup (by device) ... now see what changed
  * in the tree that's rooted at this device.
  */
-static int finish_device_resume(struct usb_device *udev)
+static int finish_port_resume(struct usb_device *udev)
 {
        int     status;
        u16     devstatus;
@@ -1783,7 +1634,6 @@ static int finish_device_resume(struct usb_device *udev)
        usb_set_device_state(udev, udev->actconfig
                        ? USB_STATE_CONFIGURED
                        : USB_STATE_ADDRESS);
-       udev->dev.power.power_state = PMSG_ON;
 
        /* 10.5.4.5 says be sure devices in the tree are still there.
         * For now let's assume the device didn't go crazy on resume,
@@ -1798,9 +1648,6 @@ static int finish_device_resume(struct usb_device *udev)
                        "gone after usb resume? status %d\n",
                        status);
        else if (udev->actconfig) {
-               unsigned        i;
-               int             (*resume)(struct device *);
-
                le16_to_cpus(&devstatus);
                if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
                                && udev->parent) {
@@ -1811,24 +1658,9 @@ static int finish_device_resume(struct usb_device *udev)
                                        USB_DEVICE_REMOTE_WAKEUP, 0,
                                        NULL, 0,
                                        USB_CTRL_SET_TIMEOUT);
-                       if (status) {
+                       if (status)
                                dev_dbg(&udev->dev, "disable remote "
                                        "wakeup, status %d\n", status);
-                               status = 0;
-                       }
-               }
-
-               /* resume interface drivers; if this is a hub, it
-                * may have a child resume event to deal with soon
-                */
-               resume = udev->dev.bus->resume;
-               for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
-                       struct device *dev =
-                                       &udev->actconfig->interface[i]->dev;
-
-                       down(&dev->sem);
-                       (void) resume(dev);
-                       up(&dev->sem);
                }
                status = 0;
 
@@ -1839,8 +1671,6 @@ static int finish_device_resume(struct usb_device *udev)
        return status;
 }
 
-#ifdef CONFIG_USB_SUSPEND
-
 static int
 hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 {
@@ -1848,6 +1678,8 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 
        // dev_dbg(hub->intfdev, "resume port %d\n", port1);
 
+       set_bit(port1, hub->busy_bits);
+
        /* see 7.1.7.7; affects power usage, but not budgeting */
        status = clear_port_feature(hub->hdev,
                        port1, USB_PORT_FEAT_SUSPEND);
@@ -1861,7 +1693,8 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
 
                /* drive resume for at least 20 msec */
                if (udev)
-                       dev_dbg(&udev->dev, "RESUME\n");
+                       dev_dbg(&udev->dev, "usb %sresume\n",
+                                       udev->auto_pm ? "auto-" : "");
                msleep(25);
 
 #define LIVE_FLAGS     ( USB_PORT_STAT_POWER \
@@ -1891,19 +1724,21 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
                        /* TRSMRCY = 10 msec */
                        msleep(10);
                        if (udev)
-                               status = finish_device_resume(udev);
+                               status = finish_port_resume(udev);
                }
        }
        if (status < 0)
                hub_port_logical_disconnect(hub, port1);
 
+       clear_bit(port1, hub->busy_bits);
+       if (!hub->hdev->parent && !hub->busy_bits[0])
+               usb_enable_root_hub_irq(hub->hdev->bus);
+
        return status;
 }
 
-#endif
-
 /*
- * usb_resume_device - re-activate a suspended usb device
+ * usb_port_resume - re-activate a suspended usb device's upstream port
  * @udev: device to re-activate
  * Context: must be able to sleep; device not locked; pm locks held
  *
@@ -1915,36 +1750,24 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
  *
  * Returns 0 on success, else negative errno.
  */
-int usb_resume_device(struct usb_device *udev)
+int usb_port_resume(struct usb_device *udev)
 {
        int     status;
 
-       if (udev->state == USB_STATE_NOTATTACHED)
-               return -ENODEV;
-
-       /* selective resume of one downstream hub-to-device port */
+       /* we change the device's upstream USB link,
+        * but root hubs have no upstream USB link.
+        */
        if (udev->parent) {
-#ifdef CONFIG_USB_SUSPEND
-               if (udev->state == USB_STATE_SUSPENDED) {
-                       // NOTE swsusp may bork us, device state being wrong...
-                       // NOTE this fails if parent is also suspended...
-                       status = hub_port_resume(hdev_to_hub(udev->parent),
-                                       udev->portnum, udev);
-               } else
-#endif
-                       status = 0;
-       } else
-               status = finish_device_resume(udev);
-       if (status < 0)
-               dev_dbg(&udev->dev, "can't resume, status %d\n",
-                       status);
-
-       /* rebind drivers that had no suspend() */
-       if (status == 0) {
-               usb_unlock_device(udev);
-               bus_rescan_devices(&usb_bus_type);
-               usb_lock_device(udev);
+               // NOTE this fails if parent is also suspended...
+               status = hub_port_resume(hdev_to_hub(udev->parent),
+                               udev->portnum, udev);
+       } else {
+               dev_dbg(&udev->dev, "usb %sresume\n",
+                               udev->auto_pm ? "auto-" : "");
+               status = finish_port_resume(udev);
        }
+       if (status < 0)
+               dev_dbg(&udev->dev, "can't resume, status %d\n", status);
        return status;
 }
 
@@ -1952,23 +1775,60 @@ static int remote_wakeup(struct usb_device *udev)
 {
        int     status = 0;
 
-#ifdef CONFIG_USB_SUSPEND
+       /* All this just to avoid sending a port-resume message
+        * to the parent hub! */
 
-       /* don't repeat RESUME sequence if this device
-        * was already woken up by some other task
-        */
        usb_lock_device(udev);
+       mutex_lock_nested(&udev->pm_mutex, udev->level);
        if (udev->state == USB_STATE_SUSPENDED) {
-               dev_dbg(&udev->dev, "RESUME (wakeup)\n");
+               dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
                /* TRSMRCY = 10 msec */
                msleep(10);
-               status = finish_device_resume(udev);
+               status = finish_port_resume(udev);
+               if (status == 0)
+                       udev->dev.power.power_state.event = PM_EVENT_ON;
        }
+       mutex_unlock(&udev->pm_mutex);
+
+       if (status == 0)
+               usb_autoresume_device(udev, 0);
        usb_unlock_device(udev);
-#endif
        return status;
 }
 
+#else  /* CONFIG_USB_SUSPEND */
+
+/* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */
+
+int usb_port_suspend(struct usb_device *udev)
+{
+       return 0;
+}
+
+static inline int
+finish_port_resume(struct usb_device *udev)
+{
+       return 0;
+}
+
+static inline int
+hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
+{
+       return 0;
+}
+
+int usb_port_resume(struct usb_device *udev)
+{
+       return 0;
+}
+
+static inline int remote_wakeup(struct usb_device *udev)
+{
+       return 0;
+}
+
+#endif
+
 static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
 {
        struct usb_hub          *hub = usb_get_intfdata (intf);
@@ -1980,13 +1840,17 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
                struct usb_device       *udev;
 
                udev = hdev->children [port1-1];
-               if (udev && (udev->dev.power.power_state.event
-                                       == PM_EVENT_ON
+               if (udev && msg.event == PM_EVENT_SUSPEND &&
 #ifdef CONFIG_USB_SUSPEND
-                               || udev->state != USB_STATE_SUSPENDED
+                               udev->state != USB_STATE_SUSPENDED
+#else
+                               udev->dev.power.power_state.event
+                                       == PM_EVENT_ON
 #endif
-                               )) {
-                       dev_dbg(&intf->dev, "port %d nyet suspended\n", port1);
+                               ) {
+                       if (!hdev->auto_pm)
+                               dev_dbg(&intf->dev, "port %d nyet suspended\n",
+                                               port1);
                        return -EBUSY;
                }
        }
@@ -2035,66 +1899,22 @@ static int hub_resume(struct usb_interface *intf)
                }
        }
 
+       /* tell khubd to look for changes on this hub */
        hub_activate(hub);
-
-       /* REVISIT:  this recursion probably shouldn't exist.  Remove
-        * this code sometime, after retesting with different root and
-        * external hubs.
-        */
-#ifdef CONFIG_USB_SUSPEND
-       {
-       unsigned                port1;
-
-       for (port1 = 1; port1 <= hdev->maxchild; port1++) {
-               struct usb_device       *udev;
-               u16                     portstat, portchange;
-
-               udev = hdev->children [port1-1];
-               status = hub_port_status(hub, port1, &portstat, &portchange);
-               if (status == 0) {
-                       if (portchange & USB_PORT_STAT_C_SUSPEND) {
-                               clear_port_feature(hdev, port1,
-                                       USB_PORT_FEAT_C_SUSPEND);
-                               portchange &= ~USB_PORT_STAT_C_SUSPEND;
-                       }
-
-                       /* let khubd handle disconnects etc */
-                       if (portchange)
-                               continue;
-               }
-
-               if (!udev || status < 0)
-                       continue;
-               usb_lock_device(udev);
-               if (portstat & USB_PORT_STAT_SUSPEND)
-                       status = hub_port_resume(hub, port1, udev);
-               else {
-                       status = finish_device_resume(udev);
-                       if (status < 0) {
-                               dev_dbg(&intf->dev, "resume port %d --> %d\n",
-                                       port1, status);
-                               hub_port_logical_disconnect(hub, port1);
-                       }
-               }
-               usb_unlock_device(udev);
-       }
-       }
-#endif
        return 0;
 }
 
-void usb_suspend_root_hub(struct usb_device *hdev)
-{
-       struct usb_hub *hub = hdev_to_hub(hdev);
+#else  /* CONFIG_PM */
 
-       /* This also makes any led blinker stop retriggering.  We're called
-        * from irq, so the blinker might still be scheduled.  Caller promises
-        * that the root hub status URB will be canceled.
-        */
-       __hub_quiesce(hub);
-       mark_quiesced(to_usb_interface(hub->intfdev));
+static inline int remote_wakeup(struct usb_device *udev)
+{
+       return 0;
 }
 
+#define hub_suspend NULL
+#define hub_resume NULL
+#endif
+
 void usb_resume_root_hub(struct usb_device *hdev)
 {
        struct usb_hub *hub = hdev_to_hub(hdev);
@@ -2214,6 +2034,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
        int                     i, j, retval;
        unsigned                delay = HUB_SHORT_RESET_TIME;
        enum usb_device_speed   oldspeed = udev->speed;
+       char                    *speed, *type;
 
        /* root hub ports have a slightly longer reset period
         * (from USB 2.0 spec, section 7.1.7.5)
@@ -2246,8 +2067,13 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
   
        /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
         * it's fixed size except for full speed devices.
+        * For Wireless USB devices, ep0 max packet is always 512 (tho
+        * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
         */
        switch (udev->speed) {
+       case USB_SPEED_VARIABLE:        /* fixed at 512 */
+               udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512);
+               break;
        case USB_SPEED_HIGH:            /* fixed at 64 */
                udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
                break;
@@ -2265,17 +2091,21 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
                goto fail;
        }
  
+       type = "";
+       switch (udev->speed) {
+       case USB_SPEED_LOW:     speed = "low";  break;
+       case USB_SPEED_FULL:    speed = "full"; break;
+       case USB_SPEED_HIGH:    speed = "high"; break;
+       case USB_SPEED_VARIABLE:
+                               speed = "variable";
+                               type = "Wireless ";
+                               break;
+       default:                speed = "?";    break;
+       }
        dev_info (&udev->dev,
-                       "%s %s speed USB device using %s and address %d\n",
-                       (udev->config) ? "reset" : "new",
-                       ({ char *speed; switch (udev->speed) {
-                       case USB_SPEED_LOW:     speed = "low";  break;
-                       case USB_SPEED_FULL:    speed = "full"; break;
-                       case USB_SPEED_HIGH:    speed = "high"; break;
-                       default:                speed = "?";    break;
-                       }; speed;}),
-                       udev->bus->controller->driver->name,
-                       udev->devnum);
+                 "%s %s speed %sUSB device using %s and address %d\n",
+                 (udev->config) ? "reset" : "new", speed, type,
+                 udev->bus->controller->driver->name, udev->devnum);
 
        /* Set up TT records, if needed  */
        if (hdev->tt) {
@@ -2317,6 +2147,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
                         * down tremendously by NAKing the unexpectedly
                         * early status stage.  Also, retry on all errors;
                         * some devices are flakey.
+                        * 255 is for WUSB devices, we actually need to use 512.
+                        * WUSB1.0[4.8.1].
                         */
                        for (j = 0; j < 3; ++j) {
                                buf->bMaxPacketSize0 = 0;
@@ -2326,7 +2158,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
                                        buf, GET_DESCRIPTOR_BUFSIZE,
                                        (i ? USB_CTRL_GET_TIMEOUT : 1000));
                                switch (buf->bMaxPacketSize0) {
-                               case 8: case 16: case 32: case 64:
+                               case 8: case 16: case 32: case 64: case 255:
                                        if (buf->bDescriptorType ==
                                                        USB_DT_DEVICE) {
                                                r = 0;
@@ -2400,7 +2232,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
        if (retval)
                goto fail;
 
-       i = udev->descriptor.bMaxPacketSize0;
+       i = udev->descriptor.bMaxPacketSize0 == 0xff?
+           512 : udev->descriptor.bMaxPacketSize0;
        if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
                if (udev->speed != USB_SPEED_FULL ||
                                !(i == 8 || i == 16 || i == 32 || i == 64)) {
@@ -2585,6 +2418,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
                usb_set_device_state(udev, USB_STATE_POWERED);
                udev->speed = USB_SPEED_UNKNOWN;
                udev->bus_mA = hub->mA_per_port;
+               udev->level = hdev->level + 1;
 
                /* set the address */
                choose_address(udev);
@@ -2736,17 +2570,6 @@ static void hub_events(void)
                usb_get_intf(intf);
                spin_unlock_irq(&hub_event_lock);
 
-               /* Is this is a root hub wanting to reactivate the downstream
-                * ports?  If so, be sure the interface resumes even if its
-                * stub "device" node was never suspended.
-                */
-               if (i) {
-                       dpm_runtime_resume(&hdev->dev);
-                       dpm_runtime_resume(&intf->dev);
-                       usb_put_intf(intf);
-                       continue;
-               }
-
                /* Lock the device, then check to see if we were
                 * disconnected while waiting for the lock to succeed. */
                if (locktree(hdev) < 0) {
@@ -2763,6 +2586,13 @@ static void hub_events(void)
                        goto loop;
                }
 
+               /* Is this is a root hub wanting to reactivate the downstream
+                * ports?  If so, be sure the interface resumes even if its
+                * stub "device" node was never suspended.
+                */
+               if (i)
+                       usb_autoresume_device(hdev, 0);
+
                /* If this is an inactive or suspended hub, do nothing */
                if (hub->quiescing)
                        goto loop;
@@ -2900,7 +2730,7 @@ static void hub_events(void)
 
                /* If this is a root hub, tell the HCD it's okay to
                 * re-enable port-change interrupts now. */
-               if (!hdev->parent)
+               if (!hdev->parent && !hub->busy_bits[0])
                        usb_enable_root_hub_irq(hdev->bus);
 
 loop:
@@ -3075,6 +2905,9 @@ int usb_reset_device(struct usb_device *udev)
                        break;
        }
        clear_bit(port1, parent_hub->busy_bits);
+       if (!parent_hdev->parent && !parent_hub->busy_bits[0])
+               usb_enable_root_hub_irq(parent_hdev->bus);
+
        if (ret < 0)
                goto re_enumerate;
  
@@ -3128,6 +2961,7 @@ re_enumerate:
        hub_port_logical_disconnect(parent_hub, port1);
        return -ENODEV;
 }
+EXPORT_SYMBOL(usb_reset_device);
 
 /**
  * usb_reset_composite_device - warn interface drivers and perform a USB port reset
@@ -3163,6 +2997,9 @@ int usb_reset_composite_device(struct usb_device *udev,
                return -EINVAL;
        }
 
+       /* Prevent autosuspend during the reset */
+       usb_autoresume_device(udev, 1);
+
        if (iface && iface->condition != USB_INTERFACE_BINDING)
                iface = NULL;
 
@@ -3204,5 +3041,7 @@ int usb_reset_composite_device(struct usb_device *udev,
                }
        }
 
+       usb_autosuspend_device(udev, 1);
        return ret;
 }
+EXPORT_SYMBOL(usb_reset_composite_device);
index 29d5f45a8456369f39dd1ed79d8853b40a5cefa7..0f8e82a4d48067da7d547344e41e30b28c123b55 100644 (file)
@@ -212,7 +212,8 @@ struct usb_hub {
        unsigned long           event_bits[1];  /* status change bitmask */
        unsigned long           change_bits[1]; /* ports with logical connect
                                                        status change */
-       unsigned long           busy_bits[1];   /* ports being reset */
+       unsigned long           busy_bits[1];   /* ports being reset or
+                                                       resumed */
 #if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
 #error event_bits[] is too short!
 #endif
index 3182c2224ba24f79c428242e431eaff03bbeba51..df3d152f0493dbb5dfcd3e76195f370791a78876 100644 (file)
@@ -44,7 +44,7 @@
 #include "hcd.h"
 
 static struct super_operations usbfs_ops;
-static struct file_operations default_file_operations;
+static const struct file_operations default_file_operations;
 static struct vfsmount *usbfs_mount;
 static int usbfs_mount_count;  /* = 0 */
 static int ignore_mount = 0;
@@ -249,7 +249,6 @@ static struct inode *usbfs_get_inode (struct super_block *sb, int mode, dev_t de
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                switch (mode & S_IFMT) {
@@ -402,13 +401,13 @@ static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
 
 static int default_open (struct inode *inode, struct file *file)
 {
-       if (inode->u.generic_ip)
-               file->private_data = inode->u.generic_ip;
+       if (inode->i_private)
+               file->private_data = inode->i_private;
 
        return 0;
 }
 
-static struct file_operations default_file_operations = {
+static const struct file_operations default_file_operations = {
        .read =         default_read_file,
        .write =        default_write_file,
        .open =         default_open,
@@ -495,7 +494,7 @@ static int fs_create_by_name (const char *name, mode_t mode,
 
 static struct dentry *fs_create_file (const char *name, mode_t mode,
                                      struct dentry *parent, void *data,
-                                     struct file_operations *fops,
+                                     const struct file_operations *fops,
                                      uid_t uid, gid_t gid)
 {
        struct dentry *dentry;
@@ -509,7 +508,7 @@ static struct dentry *fs_create_file (const char *name, mode_t mode,
        } else {
                if (dentry->d_inode) {
                        if (data)
-                               dentry->d_inode->u.generic_ip = data;
+                               dentry->d_inode->i_private = data;
                        if (fops)
                                dentry->d_inode->i_fop = fops;
                        dentry->d_inode->i_uid = uid;
index 4cc8d3e67db795f54f5f8dcc1d5a393c391796eb..85b1cd18336f03c63b875c2431f87942eb43c007 100644 (file)
@@ -23,59 +23,44 @@ static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
 }
 
 
-static void timeout_kill(unsigned long data)
-{
-       struct urb      *urb = (struct urb *) data;
-
-       usb_unlink_urb(urb);
-}
-
-// Starts urb and waits for completion or timeout
-// note that this call is NOT interruptible, while
-// many device driver i/o requests should be interruptible
-static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
+/*
+ * Starts urb and waits for completion or timeout. Note that this call
+ * is NOT interruptible. Many device driver i/o requests should be
+ * interruptible and therefore these drivers should implement their
+ * own interruptible routines.
+ */
+static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
 { 
-       struct completion       done;
-       struct timer_list       timer;
-       int                     status;
+       struct completion done;
+       unsigned long expire;
+       int status;
 
        init_completion(&done);         
        urb->context = &done;
        urb->actual_length = 0;
        status = usb_submit_urb(urb, GFP_NOIO);
-
-       if (status == 0) {
-               if (timeout > 0) {
-                       init_timer(&timer);
-                       timer.expires = jiffies + msecs_to_jiffies(timeout);
-                       timer.data = (unsigned long)urb;
-                       timer.function = timeout_kill;
-                       /* grr.  timeout _should_ include submit delays. */
-                       add_timer(&timer);
-               }
-               wait_for_completion(&done);
+       if (unlikely(status))
+               goto out;
+
+       expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
+       if (!wait_for_completion_timeout(&done, expire)) {
+
+               dev_dbg(&urb->dev->dev,
+                       "%s timed out on ep%d%s len=%d/%d\n",
+                       current->comm,
+                       usb_pipeendpoint(urb->pipe),
+                       usb_pipein(urb->pipe) ? "in" : "out",
+                       urb->actual_length,
+                       urb->transfer_buffer_length);
+
+               usb_kill_urb(urb);
+               status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
+       } else
                status = urb->status;
-               /* note:  HCDs return ETIMEDOUT for other reasons too */
-               if (status == -ECONNRESET) {
-                       dev_dbg(&urb->dev->dev,
-                               "%s timed out on ep%d%s len=%d/%d\n",
-                               current->comm,
-                               usb_pipeendpoint(urb->pipe),
-                               usb_pipein(urb->pipe) ? "in" : "out",
-                               urb->actual_length,
-                               urb->transfer_buffer_length
-                               );
-                       if (urb->actual_length > 0)
-                               status = 0;
-                       else
-                               status = -ETIMEDOUT;
-               }
-               if (timeout > 0)
-                       del_timer_sync(&timer);
-       }
-
+out:
        if (actual_length)
                *actual_length = urb->actual_length;
+
        usb_free_urb(urb);
        return status;
 }
@@ -263,7 +248,7 @@ static void sg_clean (struct usb_sg_request *io)
 
 static void sg_complete (struct urb *urb, struct pt_regs *regs)
 {
-       struct usb_sg_request   *io = (struct usb_sg_request *) urb->context;
+       struct usb_sg_request   *io = urb->context;
 
        spin_lock (&io->lock);
 
@@ -999,8 +984,8 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
                ep = dev->ep_in[epnum];
                dev->ep_in[epnum] = NULL;
        }
-       if (ep && dev->bus && dev->bus->op && dev->bus->op->disable)
-               dev->bus->op->disable(dev, ep);
+       if (ep && dev->bus)
+               usb_hcd_endpoint_disable(dev, ep);
 }
 
 /**
@@ -1381,9 +1366,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
        if (cp && configuration == 0)
                dev_warn(&dev->dev, "config 0 descriptor??\n");
 
-       if (dev->state == USB_STATE_SUSPENDED)
-               return -EHOSTUNREACH;
-
        /* Allocate memory for new interfaces before doing anything else,
         * so that if we run out then nothing will have changed. */
        n = nintf = 0;
@@ -1418,6 +1400,11 @@ free_interfaces:
                                        configuration, -i);
        }
 
+       /* Wake up the device so we can send it the Set-Config request */
+       ret = usb_autoresume_device(dev, 1);
+       if (ret)
+               goto free_interfaces;
+
        /* if it's already configured, clear out old state first.
         * getting rid of old interfaces means unbinding their drivers.
         */
@@ -1437,6 +1424,7 @@ free_interfaces:
        dev->actconfig = cp;
        if (!cp) {
                usb_set_device_state(dev, USB_STATE_ADDRESS);
+               usb_autosuspend_device(dev, 1);
                goto free_interfaces;
        }
        usb_set_device_state(dev, USB_STATE_CONFIGURED);
@@ -1505,8 +1493,68 @@ free_interfaces:
                usb_create_sysfs_intf_files (intf);
        }
 
+       usb_autosuspend_device(dev, 1);
+       return 0;
+}
+
+struct set_config_request {
+       struct usb_device       *udev;
+       int                     config;
+       struct work_struct      work;
+};
+
+/* Worker routine for usb_driver_set_configuration() */
+static void driver_set_config_work(void *_req)
+{
+       struct set_config_request *req = _req;
+
+       usb_lock_device(req->udev);
+       usb_set_configuration(req->udev, req->config);
+       usb_unlock_device(req->udev);
+       usb_put_dev(req->udev);
+       kfree(req);
+}
+
+/**
+ * usb_driver_set_configuration - Provide a way for drivers to change device configurations
+ * @udev: the device whose configuration is being updated
+ * @config: the configuration being chosen.
+ * Context: In process context, must be able to sleep
+ *
+ * Device interface drivers are not allowed to change device configurations.
+ * This is because changing configurations will destroy the interface the
+ * driver is bound to and create new ones; it would be like a floppy-disk
+ * driver telling the computer to replace the floppy-disk drive with a
+ * tape drive!
+ *
+ * Still, in certain specialized circumstances the need may arise.  This
+ * routine gets around the normal restrictions by using a work thread to
+ * submit the change-config request.
+ *
+ * Returns 0 if the request was succesfully queued, error code otherwise.
+ * The caller has no way to know whether the queued request will eventually
+ * succeed.
+ */
+int usb_driver_set_configuration(struct usb_device *udev, int config)
+{
+       struct set_config_request *req;
+
+       req = kmalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+       req->udev = udev;
+       req->config = config;
+       INIT_WORK(&req->work, driver_set_config_work, req);
+
+       usb_get_dev(udev);
+       if (!schedule_work(&req->work)) {
+               usb_put_dev(udev);
+               kfree(req);
+               return -EINVAL;
+       }
        return 0;
 }
+EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
 
 // synchronous request completion model
 EXPORT_SYMBOL(usb_control_msg);
index b042676af0a5b11b70b1fa9e422aba2de4f2a551..6b36897ca151998ab28f07c12f0e9baef9e372fe 100644 (file)
@@ -50,8 +50,11 @@ void usb_notify_add_device(struct usb_device *udev)
 
 void usb_notify_remove_device(struct usb_device *udev)
 {
+       /* Protect against simultaneous usbfs open */
+       mutex_lock(&usbfs_mutex);
        blocking_notifier_call_chain(&usb_notifier_list,
                        USB_DEVICE_REMOVE, udev);
+       mutex_unlock(&usbfs_mutex);
 }
 
 void usb_notify_add_bus(struct usb_bus *ubus)
index dec973affb0f5b2639d9bbaeb237726c0bbd9d56..55d8f575206d6b1dcbfb0338e48a79b735a7ef9d 100644 (file)
@@ -60,7 +60,7 @@ static ssize_t
 set_bConfigurationValue (struct device *dev, struct device_attribute *attr,
                const char *buf, size_t count)
 {
-       struct usb_device       *udev = udev = to_usb_device (dev);
+       struct usb_device       *udev = to_usb_device (dev);
        int                     config, value;
 
        if (sscanf (buf, "%u", &config) != 1 || config > 255)
@@ -186,6 +186,7 @@ usb_descriptor_attr (bMaxPacketSize0, "%d\n")
 
 static struct attribute *dev_attrs[] = {
        /* current configuration's attributes */
+       &dev_attr_configuration.attr,
        &dev_attr_bNumInterfaces.attr,
        &dev_attr_bConfigurationValue.attr,
        &dev_attr_bmAttributes.attr,
@@ -209,20 +210,40 @@ static struct attribute_group dev_attr_grp = {
        .attrs = dev_attrs,
 };
 
-void usb_create_sysfs_dev_files (struct usb_device *udev)
+int usb_create_sysfs_dev_files(struct usb_device *udev)
 {
        struct device *dev = &udev->dev;
+       int retval;
 
-       sysfs_create_group(&dev->kobj, &dev_attr_grp);
+       retval = sysfs_create_group(&dev->kobj, &dev_attr_grp);
+       if (retval)
+               return retval;
 
-       if (udev->manufacturer)
-               device_create_file (dev, &dev_attr_manufacturer);
-       if (udev->product)
-               device_create_file (dev, &dev_attr_product);
-       if (udev->serial)
-               device_create_file (dev, &dev_attr_serial);
-       device_create_file (dev, &dev_attr_configuration);
-       usb_create_ep_files(dev, &udev->ep0, udev);
+       if (udev->manufacturer) {
+               retval = device_create_file (dev, &dev_attr_manufacturer);
+               if (retval)
+                       goto error;
+       }
+       if (udev->product) {
+               retval = device_create_file (dev, &dev_attr_product);
+               if (retval)
+                       goto error;
+       }
+       if (udev->serial) {
+               retval = device_create_file (dev, &dev_attr_serial);
+               if (retval)
+                       goto error;
+       }
+       retval = usb_create_ep_files(dev, &udev->ep0, udev);
+       if (retval)
+               goto error;
+       return 0;
+error:
+       usb_remove_ep_files(&udev->ep0);
+       device_remove_file(dev, &dev_attr_manufacturer);
+       device_remove_file(dev, &dev_attr_product);
+       device_remove_file(dev, &dev_attr_serial);
+       return retval;
 }
 
 void usb_remove_sysfs_dev_files (struct usb_device *udev)
@@ -238,7 +259,6 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
                device_remove_file(dev, &dev_attr_product);
        if (udev->serial)
                device_remove_file(dev, &dev_attr_serial);
-       device_remove_file (dev, &dev_attr_configuration);
 }
 
 /* Interface fields */
@@ -340,18 +360,28 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
                usb_remove_ep_files(&iface_desc->endpoint[i]);
 }
 
-void usb_create_sysfs_intf_files (struct usb_interface *intf)
+int usb_create_sysfs_intf_files(struct usb_interface *intf)
 {
        struct usb_device *udev = interface_to_usbdev(intf);
        struct usb_host_interface *alt = intf->cur_altsetting;
+       int retval;
 
-       sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
+       retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
+       if (retval)
+               goto error;
 
        if (alt->string == NULL)
                alt->string = usb_cache_string(udev, alt->desc.iInterface);
        if (alt->string)
-               device_create_file(&intf->dev, &dev_attr_interface);
+               retval = device_create_file(&intf->dev, &dev_attr_interface);
        usb_create_intf_ep_files(intf, udev);
+       return 0;
+error:
+       if (alt->string)
+               device_remove_file(&intf->dev, &dev_attr_interface);
+       sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
+       usb_remove_intf_ep_files(intf);
+       return retval;
 }
 
 void usb_remove_sysfs_intf_files (struct usb_interface *intf)
index 9864988377c74c11c052336a2065be1bdf8c54c7..9801d08edacf8db26056175116d28df45af985ed 100644 (file)
@@ -57,7 +57,7 @@ struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
 {
        struct urb *urb;
 
-       urb = (struct urb *)kmalloc(sizeof(struct urb) + 
+       urb = kmalloc(sizeof(struct urb) +
                iso_packets * sizeof(struct usb_iso_packet_descriptor),
                mem_flags);
        if (!urb) {
@@ -221,7 +221,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
 {
        int                     pipe, temp, max;
        struct usb_device       *dev;
-       struct usb_operations   *op;
        int                     is_out;
 
        if (!urb || urb->hcpriv || !urb->complete)
@@ -233,8 +232,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
        if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
                        || dev->state == USB_STATE_SUSPENDED)
                return -EHOSTUNREACH;
-       if (!(op = dev->bus->op) || !op->submit_urb)
-               return -ENODEV;
 
        urb->status = -EINPROGRESS;
        urb->actual_length = 0;
@@ -376,7 +373,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
                urb->interval = temp;
        }
 
-       return op->submit_urb (urb, mem_flags);
+       return usb_hcd_submit_urb (urb, mem_flags);
 }
 
 /*-------------------------------------------------------------------*/
@@ -440,9 +437,9 @@ int usb_unlink_urb(struct urb *urb)
 {
        if (!urb)
                return -EINVAL;
-       if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
+       if (!(urb->dev && urb->dev->bus))
                return -ENODEV;
-       return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
+       return usb_hcd_unlink_urb(urb, -ECONNRESET);
 }
 
 /**
@@ -468,13 +465,13 @@ int usb_unlink_urb(struct urb *urb)
 void usb_kill_urb(struct urb *urb)
 {
        might_sleep();
-       if (!(urb && urb->dev && urb->dev->bus && urb->dev->bus->op))
+       if (!(urb && urb->dev && urb->dev->bus))
                return;
        spin_lock_irq(&urb->lock);
        ++urb->reject;
        spin_unlock_irq(&urb->lock);
 
-       urb->dev->bus->op->unlink_urb(urb, -ENOENT);
+       usb_hcd_unlink_urb(urb, -ENOENT);
        wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
 
        spin_lock_irq(&urb->lock);
index 184c24660a4c572b89fd4175d24314dd1fcb8f6c..60ef4ef0101ae727567ec07bdd82d5b73cbf102e 100644 (file)
@@ -67,7 +67,8 @@ static int nousb;     /* Disable USB when built into kernel image */
  * Don't call this function unless you are bound to one of the interfaces
  * on this device or you have locked the device!
  */
-struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
+struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
+                                     unsigned ifnum)
 {
        struct usb_host_config *config = dev->actconfig;
        int i;
@@ -100,8 +101,8 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
  * Don't call this function unless you are bound to the intf interface
  * or you have locked the device!
  */
-struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf,
-               unsigned int altnum)
+struct usb_host_interface *usb_altnum_to_altsetting(const struct usb_interface *intf,
+                                                   unsigned int altnum)
 {
        int i;
 
@@ -112,87 +113,6 @@ struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf,
        return NULL;
 }
 
-/**
- * usb_driver_claim_interface - bind a driver to an interface
- * @driver: the driver to be bound
- * @iface: the interface to which it will be bound; must be in the
- *     usb device's active configuration
- * @priv: driver data associated with that interface
- *
- * This is used by usb device drivers that need to claim more than one
- * interface on a device when probing (audio and acm are current examples).
- * No device driver should directly modify internal usb_interface or
- * usb_device structure members.
- *
- * Few drivers should need to use this routine, since the most natural
- * way to bind to an interface is to return the private data from
- * the driver's probe() method.
- *
- * Callers must own the device lock and the driver model's usb_bus_type.subsys
- * writelock.  So driver probe() entries don't need extra locking,
- * but other call contexts may need to explicitly claim those locks.
- */
-int usb_driver_claim_interface(struct usb_driver *driver,
-                               struct usb_interface *iface, void* priv)
-{
-       struct device *dev = &iface->dev;
-
-       if (dev->driver)
-               return -EBUSY;
-
-       dev->driver = &driver->driver;
-       usb_set_intfdata(iface, priv);
-       iface->condition = USB_INTERFACE_BOUND;
-       mark_active(iface);
-
-       /* if interface was already added, bind now; else let
-        * the future device_add() bind it, bypassing probe()
-        */
-       if (device_is_registered(dev))
-               device_bind_driver(dev);
-
-       return 0;
-}
-
-/**
- * usb_driver_release_interface - unbind a driver from an interface
- * @driver: the driver to be unbound
- * @iface: the interface from which it will be unbound
- *
- * This can be used by drivers to release an interface without waiting
- * for their disconnect() methods to be called.  In typical cases this
- * also causes the driver disconnect() method to be called.
- *
- * This call is synchronous, and may not be used in an interrupt context.
- * Callers must own the device lock and the driver model's usb_bus_type.subsys
- * writelock.  So driver disconnect() entries don't need extra locking,
- * but other call contexts may need to explicitly claim those locks.
- */
-void usb_driver_release_interface(struct usb_driver *driver,
-                                       struct usb_interface *iface)
-{
-       struct device *dev = &iface->dev;
-
-       /* this should never happen, don't release something that's not ours */
-       if (!dev->driver || dev->driver != &driver->driver)
-               return;
-
-       /* don't release from within disconnect() */
-       if (iface->condition != USB_INTERFACE_BOUND)
-               return;
-
-       /* don't release if the interface hasn't been added yet */
-       if (device_is_registered(dev)) {
-               iface->condition = USB_INTERFACE_UNBINDING;
-               device_release_driver(dev);
-       }
-
-       dev->driver = NULL;
-       usb_set_intfdata(iface, NULL);
-       iface->condition = USB_INTERFACE_UNBOUND;
-       mark_quiesced(iface);
-}
-
 struct find_interface_arg {
        int minor;
        struct usb_interface *interface;
@@ -204,7 +124,7 @@ static int __find_interface(struct device * dev, void * data)
        struct usb_interface *intf;
 
        /* can't look at usb devices, only interfaces */
-       if (dev->driver == &usb_generic_driver)
+       if (is_usb_device(dev))
                return 0;
 
        intf = to_usb_interface(dev);
@@ -227,127 +147,16 @@ static int __find_interface(struct device * dev, void * data)
 struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 {
        struct find_interface_arg argb;
+       int retval;
 
        argb.minor = minor;
        argb.interface = NULL;
-       driver_for_each_device(&drv->driver, NULL, &argb, __find_interface);
+       /* eat the error, it will be in argb.interface */
+       retval = driver_for_each_device(&drv->drvwrap.driver, NULL, &argb,
+                                       __find_interface);
        return argb.interface;
 }
 
-#ifdef CONFIG_HOTPLUG
-
-/*
- * This sends an uevent to userspace, typically helping to load driver
- * or other modules, configure the device, and more.  Drivers can provide
- * a MODULE_DEVICE_TABLE to help with module loading subtasks.
- *
- * We're called either from khubd (the typical case) or from root hub
- * (init, kapmd, modprobe, rmmod, etc), but the agents need to handle
- * delays in event delivery.  Use sysfs (and DEVPATH) to make sure the
- * device (and this configuration!) are still present.
- */
-static int usb_uevent(struct device *dev, char **envp, int num_envp,
-                     char *buffer, int buffer_size)
-{
-       struct usb_interface *intf;
-       struct usb_device *usb_dev;
-       struct usb_host_interface *alt;
-       int i = 0;
-       int length = 0;
-
-       if (!dev)
-               return -ENODEV;
-
-       /* driver is often null here; dev_dbg() would oops */
-       pr_debug ("usb %s: uevent\n", dev->bus_id);
-
-       /* Must check driver_data here, as on remove driver is always NULL */
-       if ((dev->driver == &usb_generic_driver) || 
-           (dev->driver_data == &usb_generic_driver_data))
-               return 0;
-
-       intf = to_usb_interface(dev);
-       usb_dev = interface_to_usbdev (intf);
-       alt = intf->cur_altsetting;
-
-       if (usb_dev->devnum < 0) {
-               pr_debug ("usb %s: already deleted?\n", dev->bus_id);
-               return -ENODEV;
-       }
-       if (!usb_dev->bus) {
-               pr_debug ("usb %s: bus removed?\n", dev->bus_id);
-               return -ENODEV;
-       }
-
-#ifdef CONFIG_USB_DEVICEFS
-       /* If this is available, userspace programs can directly read
-        * all the device descriptors we don't tell them about.  Or
-        * even act as usermode drivers.
-        *
-        * FIXME reduce hardwired intelligence here
-        */
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "DEVICE=/proc/bus/usb/%03d/%03d",
-                          usb_dev->bus->busnum, usb_dev->devnum))
-               return -ENOMEM;
-#endif
-
-       /* per-device configurations are common */
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "PRODUCT=%x/%x/%x",
-                          le16_to_cpu(usb_dev->descriptor.idVendor),
-                          le16_to_cpu(usb_dev->descriptor.idProduct),
-                          le16_to_cpu(usb_dev->descriptor.bcdDevice)))
-               return -ENOMEM;
-
-       /* class-based driver binding models */
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "TYPE=%d/%d/%d",
-                          usb_dev->descriptor.bDeviceClass,
-                          usb_dev->descriptor.bDeviceSubClass,
-                          usb_dev->descriptor.bDeviceProtocol))
-               return -ENOMEM;
-
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "INTERFACE=%d/%d/%d",
-                          alt->desc.bInterfaceClass,
-                          alt->desc.bInterfaceSubClass,
-                          alt->desc.bInterfaceProtocol))
-               return -ENOMEM;
-
-       if (add_uevent_var(envp, num_envp, &i,
-                          buffer, buffer_size, &length,
-                          "MODALIAS=usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
-                          le16_to_cpu(usb_dev->descriptor.idVendor),
-                          le16_to_cpu(usb_dev->descriptor.idProduct),
-                          le16_to_cpu(usb_dev->descriptor.bcdDevice),
-                          usb_dev->descriptor.bDeviceClass,
-                          usb_dev->descriptor.bDeviceSubClass,
-                          usb_dev->descriptor.bDeviceProtocol,
-                          alt->desc.bInterfaceClass,
-                          alt->desc.bInterfaceSubClass,
-                          alt->desc.bInterfaceProtocol))
-               return -ENOMEM;
-
-       envp[i] = NULL;
-
-       return 0;
-}
-
-#else
-
-static int usb_uevent(struct device *dev, char **envp,
-                       int num_envp, char *buffer, int buffer_size)
-{
-       return -ENODEV;
-}
-
-#endif /* CONFIG_HOTPLUG */
-
 /**
  * usb_release_dev - free a usb device structure when all users of it are finished.
  * @dev: device that's been disconnected
@@ -361,14 +170,33 @@ static void usb_release_dev(struct device *dev)
 
        udev = to_usb_device(dev);
 
+#ifdef CONFIG_PM
+       cancel_delayed_work(&udev->autosuspend);
+       flush_scheduled_work();
+#endif
        usb_destroy_configuration(udev);
-       usb_bus_put(udev->bus);
+       usb_put_hcd(bus_to_hcd(udev->bus));
        kfree(udev->product);
        kfree(udev->manufacturer);
        kfree(udev->serial);
        kfree(udev);
 }
 
+#ifdef CONFIG_PM
+
+/* usb_autosuspend_work - callback routine to autosuspend a USB device */
+static void usb_autosuspend_work(void *_udev)
+{
+       struct usb_device       *udev = _udev;
+
+       mutex_lock_nested(&udev->pm_mutex, udev->level);
+       udev->auto_pm = 1;
+       usb_suspend_both(udev, PMSG_SUSPEND);
+       mutex_unlock(&udev->pm_mutex);
+}
+
+#endif
+
 /**
  * usb_alloc_dev - usb device constructor (usbcore-internal)
  * @parent: hub to which device is connected; null to allocate a root hub
@@ -390,8 +218,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
        if (!dev)
                return NULL;
 
-       bus = usb_bus_get(bus);
-       if (!bus) {
+       if (!usb_get_hcd(bus_to_hcd(bus))) {
                kfree(dev);
                return NULL;
        }
@@ -399,11 +226,12 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
        device_initialize(&dev->dev);
        dev->dev.bus = &usb_bus_type;
        dev->dev.dma_mask = bus->controller->dma_mask;
-       dev->dev.driver_data = &usb_generic_driver_data;
-       dev->dev.driver = &usb_generic_driver;
        dev->dev.release = usb_release_dev;
        dev->state = USB_STATE_ATTACHED;
 
+       /* This magic assignment distinguishes devices from interfaces */
+       dev->dev.platform_data = &usb_generic_driver;
+
        INIT_LIST_HEAD(&dev->ep0.urb_list);
        dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
        dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
@@ -444,6 +272,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
        dev->parent = parent;
        INIT_LIST_HEAD(&dev->filelist);
 
+#ifdef CONFIG_PM
+       mutex_init(&dev->pm_mutex);
+       INIT_WORK(&dev->autosuspend, usb_autosuspend_work, dev);
+#endif
        return dev;
 }
 
@@ -549,7 +381,7 @@ void usb_put_intf(struct usb_interface *intf)
  * case the driver already owns the device lock.)
  */
 int usb_lock_device_for_reset(struct usb_device *udev,
-               struct usb_interface *iface)
+                             const struct usb_interface *iface)
 {
        unsigned long jiffies_expire = jiffies + HZ;
 
@@ -672,7 +504,139 @@ exit:
  */
 int usb_get_current_frame_number(struct usb_device *dev)
 {
-       return dev->bus->op->get_frame_number (dev);
+       return usb_hcd_get_frame_number (dev);
+}
+
+/**
+ * usb_endpoint_dir_in - check if the endpoint has IN direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type IN, otherwise it returns false.
+ */
+int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
+}
+
+/**
+ * usb_endpoint_dir_out - check if the endpoint has OUT direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type OUT, otherwise it returns false.
+ */
+int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+}
+
+/**
+ * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type bulk, otherwise it returns false.
+ */
+int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_BULK);
+}
+
+/**
+ * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type interrupt, otherwise it returns
+ * false.
+ */
+int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_INT);
+}
+
+/**
+ * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type isochronous, otherwise it returns
+ * false.
+ */
+int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_ISOC);
+}
+
+/**
+ * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and IN direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
+}
+
+/**
+ * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and IN direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
+}
+
+/**
+ * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and IN direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
+}
+
+/**
+ * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
+{
+       return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
 }
 
 /*-------------------------------------------------------------------*/
@@ -737,9 +701,9 @@ void *usb_buffer_alloc (
        dma_addr_t *dma
 )
 {
-       if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_alloc)
+       if (!dev || !dev->bus)
                return NULL;
-       return dev->bus->op->buffer_alloc (dev->bus, size, mem_flags, dma);
+       return hcd_buffer_alloc (dev->bus, size, mem_flags, dma);
 }
 
 /**
@@ -760,9 +724,11 @@ void usb_buffer_free (
        dma_addr_t dma
 )
 {
-       if (!dev || !dev->bus || !dev->bus->op || !dev->bus->op->buffer_free)
-               return;
-       dev->bus->op->buffer_free (dev->bus, size, addr, dma);
+       if (!dev || !dev->bus)
+               return;
+       if (!addr)
+               return;
+       hcd_buffer_free (dev->bus, size, addr, dma);
 }
 
 /**
@@ -911,8 +877,8 @@ void usb_buffer_unmap (struct urb *urb)
  *
  * Reverse the effect of this call with usb_buffer_unmap_sg().
  */
-int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int nents)
+int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe,
+                     struct scatterlist *sg, int nents)
 {
        struct usb_bus          *bus;
        struct device           *controller;
@@ -946,8 +912,8 @@ int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
  * Use this when you are re-using a scatterlist's data buffers for
  * another USB request.
  */
-void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int n_hw_ents)
+void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe,
+                          struct scatterlist *sg, int n_hw_ents)
 {
        struct usb_bus          *bus;
        struct device           *controller;
@@ -972,8 +938,8 @@ void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
  *
  * Reverses the effect of usb_buffer_map_sg().
  */
-void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int n_hw_ents)
+void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe,
+                        struct scatterlist *sg, int n_hw_ents)
 {
        struct usb_bus          *bus;
        struct device           *controller;
@@ -988,116 +954,6 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
                        usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
 }
 
-static int verify_suspended(struct device *dev, void *unused)
-{
-       if (dev->driver == NULL)
-               return 0;
-       return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
-}
-
-static int usb_generic_suspend(struct device *dev, pm_message_t message)
-{
-       struct usb_interface    *intf;
-       struct usb_driver       *driver;
-       int                     status;
-
-       /* USB devices enter SUSPEND state through their hubs, but can be
-        * marked for FREEZE as soon as their children are already idled.
-        * But those semantics are useless, so we equate the two (sigh).
-        */
-       if (dev->driver == &usb_generic_driver) {
-               if (dev->power.power_state.event == message.event)
-                       return 0;
-               /* we need to rule out bogus requests through sysfs */
-               status = device_for_each_child(dev, NULL, verify_suspended);
-               if (status)
-                       return status;
-               return usb_suspend_device (to_usb_device(dev));
-       }
-
-       if ((dev->driver == NULL) ||
-           (dev->driver_data == &usb_generic_driver_data))
-               return 0;
-
-       intf = to_usb_interface(dev);
-       driver = to_usb_driver(dev->driver);
-
-       /* with no hardware, USB interfaces only use FREEZE and ON states */
-       if (!is_active(intf))
-               return 0;
-
-       if (driver->suspend && driver->resume) {
-               status = driver->suspend(intf, message);
-               if (status)
-                       dev_err(dev, "%s error %d\n", "suspend", status);
-               else
-                       mark_quiesced(intf);
-       } else {
-               // FIXME else if there's no suspend method, disconnect...
-               dev_warn(dev, "no suspend for driver %s?\n", driver->name);
-               mark_quiesced(intf);
-               status = 0;
-       }
-       return status;
-}
-
-static int usb_generic_resume(struct device *dev)
-{
-       struct usb_interface    *intf;
-       struct usb_driver       *driver;
-       struct usb_device       *udev;
-       int                     status;
-
-       if (dev->power.power_state.event == PM_EVENT_ON)
-               return 0;
-
-       /* mark things as "on" immediately, no matter what errors crop up */
-       dev->power.power_state.event = PM_EVENT_ON;
-
-       /* devices resume through their hubs */
-       if (dev->driver == &usb_generic_driver) {
-               udev = to_usb_device(dev);
-               if (udev->state == USB_STATE_NOTATTACHED)
-                       return 0;
-               return usb_resume_device (to_usb_device(dev));
-       }
-
-       if ((dev->driver == NULL) ||
-           (dev->driver_data == &usb_generic_driver_data)) {
-               dev->power.power_state.event = PM_EVENT_FREEZE;
-               return 0;
-       }
-
-       intf = to_usb_interface(dev);
-       driver = to_usb_driver(dev->driver);
-
-       udev = interface_to_usbdev(intf);
-       if (udev->state == USB_STATE_NOTATTACHED)
-               return 0;
-
-       /* if driver was suspended, it has a resume method;
-        * however, sysfs can wrongly mark things as suspended
-        * (on the "no suspend method" FIXME path above)
-        */
-       if (driver->resume) {
-               status = driver->resume(intf);
-               if (status) {
-                       dev_err(dev, "%s error %d\n", "resume", status);
-                       mark_quiesced(intf);
-               }
-       } else
-               dev_warn(dev, "no resume for driver %s?\n", driver->name);
-       return 0;
-}
-
-struct bus_type usb_bus_type = {
-       .name =         "usb",
-       .match =        usb_device_match,
-       .uevent =       usb_uevent,
-       .suspend =      usb_generic_suspend,
-       .resume =       usb_generic_resume,
-};
-
 /* format to disable USB on kernel command line is: nousb */
 __module_param_call("", nousb, param_set_bool, param_get_bool, &nousb, 0444);
 
@@ -1141,7 +997,7 @@ static int __init usb_init(void)
        retval = usb_hub_init();
        if (retval)
                goto hub_init_failed;
-       retval = driver_register(&usb_generic_driver);
+       retval = usb_register_device_driver(&usb_generic_driver, THIS_MODULE);
        if (!retval)
                goto out;
 
@@ -1171,7 +1027,7 @@ static void __exit usb_exit(void)
        if (nousb)
                return;
 
-       driver_unregister(&usb_generic_driver);
+       usb_deregister_device_driver(&usb_generic_driver);
        usb_major_cleanup();
        usbfs_cleanup();
        usb_deregister(&usbfs_driver);
@@ -1201,20 +1057,27 @@ EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
 
 EXPORT_SYMBOL(usb_lock_device_for_reset);
 
-EXPORT_SYMBOL(usb_driver_claim_interface);
-EXPORT_SYMBOL(usb_driver_release_interface);
 EXPORT_SYMBOL(usb_find_interface);
 EXPORT_SYMBOL(usb_ifnum_to_if);
 EXPORT_SYMBOL(usb_altnum_to_altsetting);
 
-EXPORT_SYMBOL(usb_reset_device);
-EXPORT_SYMBOL(usb_reset_composite_device);
-
 EXPORT_SYMBOL(__usb_get_extra_descriptor);
 
 EXPORT_SYMBOL(usb_find_device);
 EXPORT_SYMBOL(usb_get_current_frame_number);
 
+EXPORT_SYMBOL_GPL(usb_endpoint_dir_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_dir_out);
+EXPORT_SYMBOL_GPL(usb_endpoint_xfer_bulk);
+EXPORT_SYMBOL_GPL(usb_endpoint_xfer_int);
+EXPORT_SYMBOL_GPL(usb_endpoint_xfer_isoc);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_out);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_int_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_int_out);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_in);
+EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_out);
+
 EXPORT_SYMBOL (usb_buffer_alloc);
 EXPORT_SYMBOL (usb_buffer_free);
 
index 49f69236b4201614b5a8329f7d7d12ec0309d5d5..0c09ecced6e19721be1155623499d85cbec44d1d 100644 (file)
@@ -1,10 +1,10 @@
 /* Functions local to drivers/usb/core/ */
 
-extern void usb_create_sysfs_dev_files (struct usb_device *dev);
+extern int usb_create_sysfs_dev_files (struct usb_device *dev);
 extern void usb_remove_sysfs_dev_files (struct usb_device *dev);
-extern void usb_create_sysfs_intf_files (struct usb_interface *intf);
+extern int usb_create_sysfs_intf_files (struct usb_interface *intf);
 extern void usb_remove_sysfs_intf_files (struct usb_interface *intf);
-extern void usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint,
+extern int usb_create_ep_files(struct device *parent, struct usb_host_endpoint *endpoint,
                                struct usb_device *udev);
 extern void usb_remove_ep_files(struct usb_host_endpoint *endpoint);
 
@@ -20,7 +20,6 @@ extern char *usb_cache_string(struct usb_device *udev, int index);
 extern int usb_set_configuration(struct usb_device *dev, int configuration);
 
 extern void usb_kick_khubd(struct usb_device *dev);
-extern void usb_suspend_root_hub(struct usb_device *hdev);
 extern void usb_resume_root_hub(struct usb_device *dev);
 
 extern int  usb_hub_init(void);
@@ -30,28 +29,74 @@ extern void usb_major_cleanup(void);
 extern int usb_host_init(void);
 extern void usb_host_cleanup(void);
 
-extern int usb_suspend_device(struct usb_device *dev);
-extern int usb_resume_device(struct usb_device *dev);
+#ifdef CONFIG_PM
 
-extern struct device_driver usb_generic_driver;
-extern int usb_generic_driver_data;
-extern int usb_device_match(struct device *dev, struct device_driver *drv);
+extern int usb_suspend_both(struct usb_device *udev, pm_message_t msg);
+extern int usb_resume_both(struct usb_device *udev);
+extern int usb_port_suspend(struct usb_device *dev);
+extern int usb_port_resume(struct usb_device *dev);
+
+#else
+
+#define usb_suspend_both(udev, msg)    0
+static inline int usb_resume_both(struct usb_device *udev)
+{
+       return 0;
+}
+#define usb_port_suspend(dev)          0
+#define usb_port_resume(dev)           0
+
+#endif
+
+#ifdef CONFIG_USB_SUSPEND
+
+#define USB_AUTOSUSPEND_DELAY  (HZ*2)
+
+extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt);
+extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt);
+
+#else
+
+#define usb_autosuspend_device(udev, dec_busy_cnt)     do {} while (0)
+#define usb_autoresume_device(udev, inc_busy_cnt)      0
+
+#endif
+
+extern struct bus_type usb_bus_type;
+extern struct usb_device_driver usb_generic_driver;
+
+/* Here's how we tell apart devices and interfaces.  Luckily there's
+ * no such thing as a platform USB device, so we can steal the use
+ * of the platform_data field. */
+
+static inline int is_usb_device(const struct device *dev)
+{
+       return dev->platform_data == &usb_generic_driver;
+}
+
+/* Do the same for device drivers and interface drivers. */
+
+static inline int is_usb_device_driver(struct device_driver *drv)
+{
+       return container_of(drv, struct usbdrv_wrap, driver)->
+                       for_devices;
+}
 
 /* Interfaces and their "power state" are owned by usbcore */
 
 static inline void mark_active(struct usb_interface *f)
 {
-       f->dev.power.power_state.event = PM_EVENT_ON;
+       f->is_active = 1;
 }
 
 static inline void mark_quiesced(struct usb_interface *f)
 {
-       f->dev.power.power_state.event = PM_EVENT_FREEZE;
+       f->is_active = 0;
 }
 
-static inline int is_active(struct usb_interface *f)
+static inline int is_active(const struct usb_interface *f)
 {
-       return f->dev.power.power_state.event == PM_EVENT_ON;
+       return f->is_active;
 }
 
 
@@ -59,9 +104,10 @@ static inline int is_active(struct usb_interface *f)
 extern const char *usbcore_name;
 
 /* usbfs stuff */
+extern struct mutex usbfs_mutex;
 extern struct usb_driver usbfs_driver;
-extern struct file_operations usbfs_devices_fops;
-extern struct file_operations usbfs_device_file_operations;
+extern const struct file_operations usbfs_devices_fops;
+extern const struct file_operations usbfs_device_file_operations;
 extern void usbfs_conn_disc_event(void);
 
 extern int usbdev_init(void);
index 1a32d96774b42d61ce0e33abe3b38b8c350fde10..8e5dd6f29d0bc18ed7c5b7ac453f67475cd1125d 100644 (file)
@@ -26,7 +26,7 @@ config USB_GADGET
           you need a low level bus controller driver, and some software
           talking to it.  Peripheral controllers are often discrete silicon,
           or are integrated with the CPU in a microcontroller.  The more
-          familiar host side controllers have names like like "EHCI", "OHCI",
+          familiar host side controllers have names like "EHCI", "OHCI",
           or "UHCI", and are usually integrated into southbridges on PC
           motherboards.
 
@@ -404,6 +404,20 @@ config USB_G_SERIAL
          which includes instructions and a "driver info file" needed to
          make MS-Windows work with this driver.
 
+config USB_MIDI_GADGET
+       tristate "MIDI Gadget (EXPERIMENTAL)"
+       depends on SND && EXPERIMENTAL
+       select SND_RAWMIDI
+       help
+         The MIDI Gadget acts as a USB Audio device, with one MIDI
+         input and one MIDI output. These MIDI jacks appear as
+         a sound "card" in the ALSA sound system. Other MIDI
+         connections can then be made on the gadget system, using
+         ALSA's aconnect utility etc.
+
+         Say "y" to link the driver statically, or "m" to build a
+         dynamically linked module called "g_midi".
+
 
 # put drivers that need isochronous transfer support (for audio
 # or video class gadget drivers), or specific hardware, here.
index 5a28e61392ec4807ef0e0a63516b4d1cc59e3b51..e71e086a1cfaf4e881ff63c34c25b4145a09c166 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_AT91)                += at91_udc.o
 g_zero-objs                    := zero.o usbstring.o config.o epautoconf.o
 g_ether-objs                   := ether.o usbstring.o config.o epautoconf.o
 g_serial-objs                  := serial.o usbstring.o config.o epautoconf.o
+g_midi-objs                    := gmidi.o usbstring.o config.o epautoconf.o
 gadgetfs-objs                  := inode.o
 g_file_storage-objs            := file_storage.o usbstring.o config.o \
                                        epautoconf.o
@@ -28,4 +29,5 @@ obj-$(CONFIG_USB_ETH)         += g_ether.o
 obj-$(CONFIG_USB_GADGETFS)     += gadgetfs.o
 obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
 obj-$(CONFIG_USB_G_SERIAL)     += g_serial.o
+obj-$(CONFIG_USB_MIDI_GADGET)  += g_midi.o
 
index cfebca05ead57ca87188b40d93f08ec0c04160b1..d00958a01cfbc2fc0b0d551348a7c127c819da13 100644 (file)
@@ -247,7 +247,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
        return single_open(file, proc_udc_show, PDE(inode)->data);
 }
 
-static struct file_operations proc_ops = {
+static const struct file_operations proc_ops = {
        .open           = proc_udc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
index 7d1c22c34957bfa94ebc5dfe067a6b98ffa86e28..fdab97a27c08bdbd152cc013dc3de9091fef3fa7 100644 (file)
@@ -889,11 +889,9 @@ EXPORT_SYMBOL (net2280_set_fifo_mode);
 static void
 dummy_gadget_release (struct device *dev)
 {
-#if 0          /* usb_bus_put isn't EXPORTed! */
        struct dummy    *dum = gadget_dev_to_dummy (dev);
 
-       usb_bus_put (&dummy_to_hcd (dum)->self);
-#endif
+       usb_put_hcd (dummy_to_hcd (dum));
 }
 
 static int dummy_udc_probe (struct platform_device *pdev)
@@ -915,9 +913,7 @@ static int dummy_udc_probe (struct platform_device *pdev)
        if (rc < 0)
                return rc;
 
-#if 0          /* usb_bus_get isn't EXPORTed! */
-       usb_bus_get (&dummy_to_hcd (dum)->self);
-#endif
+       usb_get_hcd (dummy_to_hcd (dum));
 
        platform_set_drvdata (pdev, dum);
        device_create_file (&dum->gadget.dev, &dev_attr_function);
index 30299c620d97302e3dd73900568fc803c150911b..366dc0a9e52c291e8057970eca7b3de8644e53ce 100644 (file)
@@ -262,7 +262,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
 #define DEV_CONFIG_CDC
 #endif
 
-#ifdef CONFIG_USB_GADGET_MUSBHDRC
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
 #define DEV_CONFIG_CDC
 #endif
 
@@ -2014,7 +2014,7 @@ rndis_control_ack_complete (struct usb_ep *ep, struct usb_request *req)
 static int rndis_control_ack (struct net_device *net)
 {
        struct eth_dev          *dev = netdev_priv(net);
-       u32                     length;
+       int                     length;
        struct usb_request      *resp = dev->stat_req;
 
        /* in case RNDIS calls this after disconnect */
@@ -2230,6 +2230,9 @@ eth_bind (struct usb_gadget *gadget)
        if (gadget_is_pxa (gadget)) {
                /* pxa doesn't support altsettings */
                cdc = 0;
+       } else if (gadget_is_musbhdrc(gadget)) {
+               /* reduce tx dma overhead by avoiding special cases */
+               zlp = 0;
        } else if (gadget_is_sh(gadget)) {
                /* sh doesn't support multiple interfaces or configs */
                cdc = 0;
@@ -2564,7 +2567,7 @@ static struct usb_gadget_driver eth_driver = {
 
        .function       = (char *) driver_desc,
        .bind           = eth_bind,
-       .unbind         = __exit_p(eth_unbind),
+       .unbind         = eth_unbind,
 
        .setup          = eth_setup,
        .disconnect     = eth_disconnect,
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c
new file mode 100644 (file)
index 0000000..b68cecd
--- /dev/null
@@ -0,0 +1,1337 @@
+/*
+ * gmidi.c -- USB MIDI Gadget Driver
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This code is based in part on:
+ *
+ * Gadget Zero driver, Copyright (C) 2003-2004 David Brownell.
+ * USB Audio driver, Copyright (C) 2002 by Takashi Iwai.
+ * USB MIDI driver, Copyright (C) 2002-2005 Clemens Ladisch.
+ *
+ * Refer to the USB Device Class Definition for MIDI Devices:
+ * http://www.usb.org/developers/devclass_docs/midi10.pdf
+ */
+
+#define DEBUG 1
+// #define VERBOSE
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/utsname.h>
+#include <linux/device.h>
+#include <linux/moduleparam.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/rawmidi.h>
+
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/midi.h>
+
+#include "gadget_chips.h"
+
+MODULE_AUTHOR("Ben Williamson");
+MODULE_LICENSE("GPL v2");
+
+#define DRIVER_VERSION "25 Jul 2006"
+
+static const char shortname[] = "g_midi";
+static const char longname[] = "MIDI Gadget";
+
+static int index = SNDRV_DEFAULT_IDX1;
+static char *id = SNDRV_DEFAULT_STR1;
+
+module_param(index, int, 0444);
+MODULE_PARM_DESC(index, "Index value for the USB MIDI Gadget adapter.");
+module_param(id, charp, 0444);
+MODULE_PARM_DESC(id, "ID string for the USB MIDI Gadget adapter.");
+
+/* Some systems will want different product identifers published in the
+ * device descriptor, either numbers or strings or both.  These string
+ * parameters are in UTF-8 (superset of ASCII's 7 bit characters).
+ */
+
+static ushort idVendor;
+module_param(idVendor, ushort, S_IRUGO);
+MODULE_PARM_DESC(idVendor, "USB Vendor ID");
+
+static ushort idProduct;
+module_param(idProduct, ushort, S_IRUGO);
+MODULE_PARM_DESC(idProduct, "USB Product ID");
+
+static ushort bcdDevice;
+module_param(bcdDevice, ushort, S_IRUGO);
+MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
+
+static char *iManufacturer;
+module_param(iManufacturer, charp, S_IRUGO);
+MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
+
+static char *iProduct;
+module_param(iProduct, charp, S_IRUGO);
+MODULE_PARM_DESC(iProduct, "USB Product string");
+
+static char *iSerialNumber;
+module_param(iSerialNumber, charp, S_IRUGO);
+MODULE_PARM_DESC(iSerialNumber, "SerialNumber");
+
+/*
+ * this version autoconfigures as much as possible,
+ * which is reasonable for most "bulk-only" drivers.
+ */
+static const char *EP_IN_NAME;
+static const char *EP_OUT_NAME;
+
+
+/* big enough to hold our biggest descriptor */
+#define USB_BUFSIZ 256
+
+
+/* This is a gadget, and the IN/OUT naming is from the host's perspective.
+   USB -> OUT endpoint -> rawmidi
+   USB <- IN endpoint  <- rawmidi */
+struct gmidi_in_port {
+       struct gmidi_device* dev;
+       int active;
+       uint8_t cable;          /* cable number << 4 */
+       uint8_t state;
+#define STATE_UNKNOWN  0
+#define STATE_1PARAM   1
+#define STATE_2PARAM_1 2
+#define STATE_2PARAM_2 3
+#define STATE_SYSEX_0  4
+#define STATE_SYSEX_1  5
+#define STATE_SYSEX_2  6
+       uint8_t data[2];
+};
+
+struct gmidi_device {
+       spinlock_t              lock;
+       struct usb_gadget       *gadget;
+       struct usb_request      *req;           /* for control responses */
+       u8                      config;
+       struct usb_ep           *in_ep, *out_ep;
+       struct snd_card         *card;
+       struct snd_rawmidi      *rmidi;
+       struct snd_rawmidi_substream *in_substream;
+       struct snd_rawmidi_substream *out_substream;
+
+       /* For the moment we only support one port in
+          each direction, but in_port is kept as a
+          separate struct so we can have more later. */
+       struct gmidi_in_port    in_port;
+       unsigned long           out_triggered;
+       struct tasklet_struct   tasklet;
+};
+
+static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req);
+
+
+#define xprintk(d,level,fmt,args...) \
+       dev_printk(level , &(d)->gadget->dev , fmt , ## args)
+
+#ifdef DEBUG
+#define DBG(dev,fmt,args...) \
+       xprintk(dev , KERN_DEBUG , fmt , ## args)
+#else
+#define DBG(dev,fmt,args...) \
+       do { } while (0)
+#endif /* DEBUG */
+
+#ifdef VERBOSE
+#define VDBG   DBG
+#else
+#define VDBG(dev,fmt,args...) \
+       do { } while (0)
+#endif /* VERBOSE */
+
+#define ERROR(dev,fmt,args...) \
+       xprintk(dev , KERN_ERR , fmt , ## args)
+#define WARN(dev,fmt,args...) \
+       xprintk(dev , KERN_WARNING , fmt , ## args)
+#define INFO(dev,fmt,args...) \
+       xprintk(dev , KERN_INFO , fmt , ## args)
+
+
+static unsigned buflen = 256;
+static unsigned qlen = 32;
+
+module_param(buflen, uint, S_IRUGO);
+module_param(qlen, uint, S_IRUGO);
+
+
+/* Thanks to Grey Innovation for donating this product ID.
+ *
+ * DO NOT REUSE THESE IDs with a protocol-incompatible driver!!  Ever!!
+ * Instead:  allocate your own, using normal USB-IF procedures.
+ */
+#define DRIVER_VENDOR_NUM      0x17b3          /* Grey Innovation */
+#define DRIVER_PRODUCT_NUM     0x0004          /* Linux-USB "MIDI Gadget" */
+
+
+/*
+ * DESCRIPTORS ... most are static, but strings and (full)
+ * configuration descriptors are built on demand.
+ */
+
+#define STRING_MANUFACTURER    25
+#define STRING_PRODUCT         42
+#define STRING_SERIAL          101
+#define STRING_MIDI_GADGET     250
+
+/* We only have the one configuration, it's number 1. */
+#define        GMIDI_CONFIG            1
+
+/* We have two interfaces- AudioControl and MIDIStreaming */
+#define GMIDI_AC_INTERFACE     0
+#define GMIDI_MS_INTERFACE     1
+#define GMIDI_NUM_INTERFACES   2
+
+DECLARE_USB_AC_HEADER_DESCRIPTOR(1);
+DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
+DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1);
+
+/* B.1  Device Descriptor */
+static struct usb_device_descriptor device_desc = {
+       .bLength =              USB_DT_DEVICE_SIZE,
+       .bDescriptorType =      USB_DT_DEVICE,
+       .bcdUSB =               __constant_cpu_to_le16(0x0200),
+       .bDeviceClass =         USB_CLASS_PER_INTERFACE,
+       .idVendor =             __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
+       .idProduct =            __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
+       .iManufacturer =        STRING_MANUFACTURER,
+       .iProduct =             STRING_PRODUCT,
+       .bNumConfigurations =   1,
+};
+
+/* B.2  Configuration Descriptor */
+static struct usb_config_descriptor config_desc = {
+       .bLength =              USB_DT_CONFIG_SIZE,
+       .bDescriptorType =      USB_DT_CONFIG,
+       /* compute wTotalLength on the fly */
+       .bNumInterfaces =       GMIDI_NUM_INTERFACES,
+       .bConfigurationValue =  GMIDI_CONFIG,
+       .iConfiguration =       STRING_MIDI_GADGET,
+       /*
+        * FIXME: When embedding this driver in a device,
+        * these need to be set to reflect the actual
+        * power properties of the device. Is it selfpowered?
+        */
+       .bmAttributes =         USB_CONFIG_ATT_ONE,
+       .bMaxPower =            1,
+};
+
+/* B.3.1  Standard AC Interface Descriptor */
+static const struct usb_interface_descriptor ac_interface_desc = {
+       .bLength =              USB_DT_INTERFACE_SIZE,
+       .bDescriptorType =      USB_DT_INTERFACE,
+       .bInterfaceNumber =     GMIDI_AC_INTERFACE,
+       .bNumEndpoints =        0,
+       .bInterfaceClass =      USB_CLASS_AUDIO,
+       .bInterfaceSubClass =   USB_SUBCLASS_AUDIOCONTROL,
+       .iInterface =           STRING_MIDI_GADGET,
+};
+
+/* B.3.2  Class-Specific AC Interface Descriptor */
+static const struct usb_ac_header_descriptor_1 ac_header_desc = {
+       .bLength =              USB_DT_AC_HEADER_SIZE(1),
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_HEADER,
+       .bcdADC =               __constant_cpu_to_le16(0x0100),
+       .wTotalLength =         USB_DT_AC_HEADER_SIZE(1),
+       .bInCollection =        1,
+       .baInterfaceNr = {
+               [0] =           GMIDI_MS_INTERFACE,
+       }
+};
+
+/* B.4.1  Standard MS Interface Descriptor */
+static const struct usb_interface_descriptor ms_interface_desc = {
+       .bLength =              USB_DT_INTERFACE_SIZE,
+       .bDescriptorType =      USB_DT_INTERFACE,
+       .bInterfaceNumber =     GMIDI_MS_INTERFACE,
+       .bNumEndpoints =        2,
+       .bInterfaceClass =      USB_CLASS_AUDIO,
+       .bInterfaceSubClass =   USB_SUBCLASS_MIDISTREAMING,
+       .iInterface =           STRING_MIDI_GADGET,
+};
+
+/* B.4.2  Class-Specific MS Interface Descriptor */
+static const struct usb_ms_header_descriptor ms_header_desc = {
+       .bLength =              USB_DT_MS_HEADER_SIZE,
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_HEADER,
+       .bcdMSC =               __constant_cpu_to_le16(0x0100),
+       .wTotalLength =         USB_DT_MS_HEADER_SIZE
+                               + 2*USB_DT_MIDI_IN_SIZE
+                               + 2*USB_DT_MIDI_OUT_SIZE(1),
+};
+
+#define JACK_IN_EMB    1
+#define JACK_IN_EXT    2
+#define JACK_OUT_EMB   3
+#define JACK_OUT_EXT   4
+
+/* B.4.3  MIDI IN Jack Descriptors */
+static const struct usb_midi_in_jack_descriptor jack_in_emb_desc = {
+       .bLength =              USB_DT_MIDI_IN_SIZE,
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_MIDI_IN_JACK,
+       .bJackType =            USB_MS_EMBEDDED,
+       .bJackID =              JACK_IN_EMB,
+};
+
+static const struct usb_midi_in_jack_descriptor jack_in_ext_desc = {
+       .bLength =              USB_DT_MIDI_IN_SIZE,
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_MIDI_IN_JACK,
+       .bJackType =            USB_MS_EXTERNAL,
+       .bJackID =              JACK_IN_EXT,
+};
+
+/* B.4.4  MIDI OUT Jack Descriptors */
+static const struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc = {
+       .bLength =              USB_DT_MIDI_OUT_SIZE(1),
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_MIDI_OUT_JACK,
+       .bJackType =            USB_MS_EMBEDDED,
+       .bJackID =              JACK_OUT_EMB,
+       .bNrInputPins =         1,
+       .pins = {
+               [0] = {
+                       .baSourceID =   JACK_IN_EXT,
+                       .baSourcePin =  1,
+               }
+       }
+};
+
+static const struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc = {
+       .bLength =              USB_DT_MIDI_OUT_SIZE(1),
+       .bDescriptorType =      USB_DT_CS_INTERFACE,
+       .bDescriptorSubtype =   USB_MS_MIDI_OUT_JACK,
+       .bJackType =            USB_MS_EXTERNAL,
+       .bJackID =              JACK_OUT_EXT,
+       .bNrInputPins =         1,
+       .pins = {
+               [0] = {
+                       .baSourceID =   JACK_IN_EMB,
+                       .baSourcePin =  1,
+               }
+       }
+};
+
+/* B.5.1  Standard Bulk OUT Endpoint Descriptor */
+static struct usb_endpoint_descriptor bulk_out_desc = {
+       .bLength =              USB_DT_ENDPOINT_AUDIO_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bEndpointAddress =     USB_DIR_OUT,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+};
+
+/* B.5.2  Class-specific MS Bulk OUT Endpoint Descriptor */
+static const struct usb_ms_endpoint_descriptor_1 ms_out_desc = {
+       .bLength =              USB_DT_MS_ENDPOINT_SIZE(1),
+       .bDescriptorType =      USB_DT_CS_ENDPOINT,
+       .bDescriptorSubtype =   USB_MS_GENERAL,
+       .bNumEmbMIDIJack =      1,
+       .baAssocJackID = {
+               [0] =           JACK_IN_EMB,
+       }
+};
+
+/* B.6.1  Standard Bulk IN Endpoint Descriptor */
+static struct usb_endpoint_descriptor bulk_in_desc = {
+       .bLength =              USB_DT_ENDPOINT_AUDIO_SIZE,
+       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bEndpointAddress =     USB_DIR_IN,
+       .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+};
+
+/* B.6.2  Class-specific MS Bulk IN Endpoint Descriptor */
+static const struct usb_ms_endpoint_descriptor_1 ms_in_desc = {
+       .bLength =              USB_DT_MS_ENDPOINT_SIZE(1),
+       .bDescriptorType =      USB_DT_CS_ENDPOINT,
+       .bDescriptorSubtype =   USB_MS_GENERAL,
+       .bNumEmbMIDIJack =      1,
+       .baAssocJackID = {
+               [0] =           JACK_OUT_EMB,
+       }
+};
+
+static const struct usb_descriptor_header *gmidi_function [] = {
+       (struct usb_descriptor_header *)&ac_interface_desc,
+       (struct usb_descriptor_header *)&ac_header_desc,
+       (struct usb_descriptor_header *)&ms_interface_desc,
+
+       (struct usb_descriptor_header *)&ms_header_desc,
+       (struct usb_descriptor_header *)&jack_in_emb_desc,
+       (struct usb_descriptor_header *)&jack_in_ext_desc,
+       (struct usb_descriptor_header *)&jack_out_emb_desc,
+       (struct usb_descriptor_header *)&jack_out_ext_desc,
+       /* If you add more jacks, update ms_header_desc.wTotalLength */
+
+       (struct usb_descriptor_header *)&bulk_out_desc,
+       (struct usb_descriptor_header *)&ms_out_desc,
+       (struct usb_descriptor_header *)&bulk_in_desc,
+       (struct usb_descriptor_header *)&ms_in_desc,
+       NULL,
+};
+
+static char manufacturer[50];
+static char product_desc[40] = "MIDI Gadget";
+static char serial_number[20];
+
+/* static strings, in UTF-8 */
+static struct usb_string strings [] = {
+       { STRING_MANUFACTURER, manufacturer, },
+       { STRING_PRODUCT, product_desc, },
+       { STRING_SERIAL, serial_number, },
+       { STRING_MIDI_GADGET, longname, },
+       {  }                    /* end of list */
+};
+
+static struct usb_gadget_strings stringtab = {
+       .language       = 0x0409,       /* en-us */
+       .strings        = strings,
+};
+
+static int config_buf(struct usb_gadget *gadget,
+               u8 *buf, u8 type, unsigned index)
+{
+       int len;
+
+       /* only one configuration */
+       if (index != 0) {
+               return -EINVAL;
+       }
+       len = usb_gadget_config_buf(&config_desc,
+                       buf, USB_BUFSIZ, gmidi_function);
+       if (len < 0) {
+               return len;
+       }
+       ((struct usb_config_descriptor *)buf)->bDescriptorType = type;
+       return len;
+}
+
+static struct usb_request* alloc_ep_req(struct usb_ep *ep, unsigned length)
+{
+       struct usb_request      *req;
+
+       req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+       if (req) {
+               req->length = length;
+               req->buf = kmalloc(length, GFP_ATOMIC);
+               if (!req->buf) {
+                       usb_ep_free_request(ep, req);
+                       req = NULL;
+               }
+       }
+       return req;
+}
+
+static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
+{
+       kfree(req->buf);
+       usb_ep_free_request(ep, req);
+}
+
+static const uint8_t gmidi_cin_length[] = {
+       0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1
+};
+
+/*
+ * Receives a chunk of MIDI data.
+ */
+static void gmidi_read_data(struct usb_ep *ep, int cable,
+                                  uint8_t* data, int length)
+{
+       struct gmidi_device *dev = ep->driver_data;
+       /* cable is ignored, because for now we only have one. */
+
+       if (!dev->out_substream) {
+               /* Nobody is listening - throw it on the floor. */
+               return;
+       }
+       if (!test_bit(dev->out_substream->number, &dev->out_triggered)) {
+               return;
+       }
+       snd_rawmidi_receive(dev->out_substream, data, length);
+}
+
+static void gmidi_handle_out_data(struct usb_ep *ep, struct usb_request *req)
+{
+       unsigned i;
+       u8 *buf = req->buf;
+
+       for (i = 0; i + 3 < req->actual; i += 4) {
+               if (buf[i] != 0) {
+                       int cable = buf[i] >> 4;
+                       int length = gmidi_cin_length[buf[i] & 0x0f];
+                       gmidi_read_data(ep, cable, &buf[i + 1], length);
+               }
+       }
+}
+
+static void gmidi_complete(struct usb_ep *ep, struct usb_request *req)
+{
+       struct gmidi_device *dev = ep->driver_data;
+       int status = req->status;
+
+       switch (status) {
+       case 0:                         /* normal completion */
+               if (ep == dev->out_ep) {
+                       /* we received stuff.
+                          req is queued again, below */
+                       gmidi_handle_out_data(ep, req);
+               } else if (ep == dev->in_ep) {
+                       /* our transmit completed.
+                          see if there's more to go.
+                          gmidi_transmit eats req, don't queue it again. */
+                       gmidi_transmit(dev, req);
+                       return;
+               }
+               break;
+
+       /* this endpoint is normally active while we're configured */
+       case -ECONNABORTED:             /* hardware forced ep reset */
+       case -ECONNRESET:               /* request dequeued */
+       case -ESHUTDOWN:                /* disconnect from host */
+               VDBG(dev, "%s gone (%d), %d/%d\n", ep->name, status,
+                               req->actual, req->length);
+               if (ep == dev->out_ep) {
+                       gmidi_handle_out_data(ep, req);
+               }
+               free_ep_req(ep, req);
+               return;
+
+       case -EOVERFLOW:                /* buffer overrun on read means that
+                                        * we didn't provide a big enough
+                                        * buffer.
+                                        */
+       default:
+               DBG(dev, "%s complete --> %d, %d/%d\n", ep->name,
+                               status, req->actual, req->length);
+               break;
+       case -EREMOTEIO:                /* short read */
+               break;
+       }
+
+       status = usb_ep_queue(ep, req, GFP_ATOMIC);
+       if (status) {
+               ERROR(dev, "kill %s:  resubmit %d bytes --> %d\n",
+                               ep->name, req->length, status);
+               usb_ep_set_halt(ep);
+               /* FIXME recover later ... somehow */
+       }
+}
+
+static int set_gmidi_config(struct gmidi_device *dev, gfp_t gfp_flags)
+{
+       int err = 0;
+       struct usb_request *req;
+       struct usb_ep* ep;
+       unsigned i;
+
+       err = usb_ep_enable(dev->in_ep, &bulk_in_desc);
+       if (err) {
+               ERROR(dev, "can't start %s: %d\n", dev->in_ep->name, err);
+               goto fail;
+       }
+       dev->in_ep->driver_data = dev;
+
+       err = usb_ep_enable(dev->out_ep, &bulk_out_desc);
+       if (err) {
+               ERROR(dev, "can't start %s: %d\n", dev->out_ep->name, err);
+               goto fail;
+       }
+       dev->out_ep->driver_data = dev;
+
+       /* allocate a bunch of read buffers and queue them all at once. */
+       ep = dev->out_ep;
+       for (i = 0; i < qlen && err == 0; i++) {
+               req = alloc_ep_req(ep, buflen);
+               if (req) {
+                       req->complete = gmidi_complete;
+                       err = usb_ep_queue(ep, req, GFP_ATOMIC);
+                       if (err) {
+                               DBG(dev, "%s queue req: %d\n", ep->name, err);
+                       }
+               } else {
+                       err = -ENOMEM;
+               }
+       }
+fail:
+       /* caller is responsible for cleanup on error */
+       return err;
+}
+
+
+static void gmidi_reset_config(struct gmidi_device *dev)
+{
+       if (dev->config == 0) {
+               return;
+       }
+
+       DBG(dev, "reset config\n");
+
+       /* just disable endpoints, forcing completion of pending i/o.
+        * all our completion handlers free their requests in this case.
+        */
+       usb_ep_disable(dev->in_ep);
+       usb_ep_disable(dev->out_ep);
+       dev->config = 0;
+}
+
+/* change our operational config.  this code must agree with the code
+ * that returns config descriptors, and altsetting code.
+ *
+ * it's also responsible for power management interactions. some
+ * configurations might not work with our current power sources.
+ *
+ * note that some device controller hardware will constrain what this
+ * code can do, perhaps by disallowing more than one configuration or
+ * by limiting configuration choices (like the pxa2xx).
+ */
+static int
+gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags)
+{
+       int result = 0;
+       struct usb_gadget *gadget = dev->gadget;
+
+#if 0
+       /* FIXME */
+       /* Hacking this bit out fixes a bug where on receipt of two
+          USB_REQ_SET_CONFIGURATION messages, we end up with no
+          buffered OUT requests waiting for data. This is clearly
+          hiding a bug elsewhere, because if the config didn't
+          change then we really shouldn't do anything. */
+       /* Having said that, when we do "change" from config 1
+          to config 1, we at least gmidi_reset_config() which
+          clears out any requests on endpoints, so it's not like
+          we leak or anything. */
+       if (number == dev->config) {
+               return 0;
+       }
+#endif
+
+       if (gadget_is_sa1100(gadget) && dev->config) {
+               /* tx fifo is full, but we can't clear it...*/
+               INFO(dev, "can't change configurations\n");
+               return -ESPIPE;
+       }
+       gmidi_reset_config(dev);
+
+       switch (number) {
+       case GMIDI_CONFIG:
+               result = set_gmidi_config(dev, gfp_flags);
+               break;
+       default:
+               result = -EINVAL;
+               /* FALL THROUGH */
+       case 0:
+               return result;
+       }
+
+       if (!result && (!dev->in_ep || !dev->out_ep)) {
+               result = -ENODEV;
+       }
+       if (result) {
+               gmidi_reset_config(dev);
+       } else {
+               char *speed;
+
+               switch (gadget->speed) {
+               case USB_SPEED_LOW:     speed = "low"; break;
+               case USB_SPEED_FULL:    speed = "full"; break;
+               case USB_SPEED_HIGH:    speed = "high"; break;
+               default:                speed = "?"; break;
+               }
+
+               dev->config = number;
+               INFO(dev, "%s speed\n", speed);
+       }
+       return result;
+}
+
+
+static void gmidi_setup_complete(struct usb_ep *ep, struct usb_request *req)
+{
+       if (req->status || req->actual != req->length) {
+               DBG((struct gmidi_device *) ep->driver_data,
+                               "setup complete --> %d, %d/%d\n",
+                               req->status, req->actual, req->length);
+       }
+}
+
+/*
+ * The setup() callback implements all the ep0 functionality that's
+ * not handled lower down, in hardware or the hardware driver (like
+ * device and endpoint feature flags, and their status).  It's all
+ * housekeeping for the gadget function we're implementing.  Most of
+ * the work is in config-specific setup.
+ */
+static int gmidi_setup(struct usb_gadget *gadget,
+                       const struct usb_ctrlrequest *ctrl)
+{
+       struct gmidi_device *dev = get_gadget_data(gadget);
+       struct usb_request *req = dev->req;
+       int value = -EOPNOTSUPP;
+       u16 w_index = le16_to_cpu(ctrl->wIndex);
+       u16 w_value = le16_to_cpu(ctrl->wValue);
+       u16 w_length = le16_to_cpu(ctrl->wLength);
+
+       /* usually this stores reply data in the pre-allocated ep0 buffer,
+        * but config change events will reconfigure hardware.
+        */
+       req->zero = 0;
+       switch (ctrl->bRequest) {
+
+       case USB_REQ_GET_DESCRIPTOR:
+               if (ctrl->bRequestType != USB_DIR_IN) {
+                       goto unknown;
+               }
+               switch (w_value >> 8) {
+
+               case USB_DT_DEVICE:
+                       value = min(w_length, (u16) sizeof(device_desc));
+                       memcpy(req->buf, &device_desc, value);
+                       break;
+               case USB_DT_CONFIG:
+                       value = config_buf(gadget, req->buf,
+                                       w_value >> 8,
+                                       w_value & 0xff);
+                       if (value >= 0) {
+                               value = min(w_length, (u16)value);
+                       }
+                       break;
+
+               case USB_DT_STRING:
+                       /* wIndex == language code.
+                        * this driver only handles one language, you can
+                        * add string tables for other languages, using
+                        * any UTF-8 characters
+                        */
+                       value = usb_gadget_get_string(&stringtab,
+                                       w_value & 0xff, req->buf);
+                       if (value >= 0) {
+                               value = min(w_length, (u16)value);
+                       }
+                       break;
+               }
+               break;
+
+       /* currently two configs, two speeds */
+       case USB_REQ_SET_CONFIGURATION:
+               if (ctrl->bRequestType != 0) {
+                       goto unknown;
+               }
+               if (gadget->a_hnp_support) {
+                       DBG(dev, "HNP available\n");
+               } else if (gadget->a_alt_hnp_support) {
+                       DBG(dev, "HNP needs a different root port\n");
+               } else {
+                       VDBG(dev, "HNP inactive\n");
+               }
+               spin_lock(&dev->lock);
+               value = gmidi_set_config(dev, w_value, GFP_ATOMIC);
+               spin_unlock(&dev->lock);
+               break;
+       case USB_REQ_GET_CONFIGURATION:
+               if (ctrl->bRequestType != USB_DIR_IN) {
+                       goto unknown;
+               }
+               *(u8 *)req->buf = dev->config;
+               value = min(w_length, (u16)1);
+               break;
+
+       /* until we add altsetting support, or other interfaces,
+        * only 0/0 are possible.  pxa2xx only supports 0/0 (poorly)
+        * and already killed pending endpoint I/O.
+        */
+       case USB_REQ_SET_INTERFACE:
+               if (ctrl->bRequestType != USB_RECIP_INTERFACE) {
+                       goto unknown;
+               }
+               spin_lock(&dev->lock);
+               if (dev->config && w_index < GMIDI_NUM_INTERFACES
+                       && w_value == 0)
+               {
+                       u8 config = dev->config;
+
+                       /* resets interface configuration, forgets about
+                        * previous transaction state (queued bufs, etc)
+                        * and re-inits endpoint state (toggle etc)
+                        * no response queued, just zero status == success.
+                        * if we had more than one interface we couldn't
+                        * use this "reset the config" shortcut.
+                        */
+                       gmidi_reset_config(dev);
+                       gmidi_set_config(dev, config, GFP_ATOMIC);
+                       value = 0;
+               }
+               spin_unlock(&dev->lock);
+               break;
+       case USB_REQ_GET_INTERFACE:
+               if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) {
+                       goto unknown;
+               }
+               if (!dev->config) {
+                       break;
+               }
+               if (w_index >= GMIDI_NUM_INTERFACES) {
+                       value = -EDOM;
+                       break;
+               }
+               *(u8 *)req->buf = 0;
+               value = min(w_length, (u16)1);
+               break;
+
+       default:
+unknown:
+               VDBG(dev, "unknown control req%02x.%02x v%04x i%04x l%d\n",
+                       ctrl->bRequestType, ctrl->bRequest,
+                       w_value, w_index, w_length);
+       }
+
+       /* respond with data transfer before status phase? */
+       if (value >= 0) {
+               req->length = value;
+               req->zero = value < w_length;
+               value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
+               if (value < 0) {
+                       DBG(dev, "ep_queue --> %d\n", value);
+                       req->status = 0;
+                       gmidi_setup_complete(gadget->ep0, req);
+               }
+       }
+
+       /* device either stalls (value < 0) or reports success */
+       return value;
+}
+
+static void gmidi_disconnect(struct usb_gadget *gadget)
+{
+       struct gmidi_device *dev = get_gadget_data(gadget);
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->lock, flags);
+       gmidi_reset_config(dev);
+
+       /* a more significant application might have some non-usb
+        * activities to quiesce here, saving resources like power
+        * or pushing the notification up a network stack.
+        */
+       spin_unlock_irqrestore(&dev->lock, flags);
+
+       /* next we may get setup() calls to enumerate new connections;
+        * or an unbind() during shutdown (including removing module).
+        */
+}
+
+static void /* __init_or_exit */ gmidi_unbind(struct usb_gadget *gadget)
+{
+       struct gmidi_device *dev = get_gadget_data(gadget);
+       struct snd_card* card;
+
+       DBG(dev, "unbind\n");
+
+       card = dev->card;
+       dev->card = NULL;
+       if (card) {
+               snd_card_free(card);
+       }
+
+       /* we've already been disconnected ... no i/o is active */
+       if (dev->req) {
+               dev->req->length = USB_BUFSIZ;
+               free_ep_req(gadget->ep0, dev->req);
+       }
+       kfree(dev);
+       set_gadget_data(gadget, NULL);
+}
+
+static int gmidi_snd_free(struct snd_device *device)
+{
+       return 0;
+}
+
+static void gmidi_transmit_packet(struct usb_request* req, uint8_t p0,
+                                       uint8_t p1, uint8_t p2, uint8_t p3)
+{
+       unsigned length = req->length;
+
+       uint8_t* buf = (uint8_t*)req->buf + length;
+       buf[0] = p0;
+       buf[1] = p1;
+       buf[2] = p2;
+       buf[3] = p3;
+       req->length = length + 4;
+}
+
+/*
+ * Converts MIDI commands to USB MIDI packets.
+ */
+static void gmidi_transmit_byte(struct usb_request* req,
+                               struct gmidi_in_port* port, uint8_t b)
+{
+       uint8_t p0 = port->cable;
+
+       if (b >= 0xf8) {
+               gmidi_transmit_packet(req, p0 | 0x0f, b, 0, 0);
+       } else if (b >= 0xf0) {
+               switch (b) {
+               case 0xf0:
+                       port->data[0] = b;
+                       port->state = STATE_SYSEX_1;
+                       break;
+               case 0xf1:
+               case 0xf3:
+                       port->data[0] = b;
+                       port->state = STATE_1PARAM;
+                       break;
+               case 0xf2:
+                       port->data[0] = b;
+                       port->state = STATE_2PARAM_1;
+                       break;
+               case 0xf4:
+               case 0xf5:
+                       port->state = STATE_UNKNOWN;
+                       break;
+               case 0xf6:
+                       gmidi_transmit_packet(req, p0 | 0x05, 0xf6, 0, 0);
+                       port->state = STATE_UNKNOWN;
+                       break;
+               case 0xf7:
+                       switch (port->state) {
+                       case STATE_SYSEX_0:
+                               gmidi_transmit_packet(req,
+                                       p0 | 0x05, 0xf7, 0, 0);
+                               break;
+                       case STATE_SYSEX_1:
+                               gmidi_transmit_packet(req,
+                                       p0 | 0x06, port->data[0], 0xf7, 0);
+                               break;
+                       case STATE_SYSEX_2:
+                               gmidi_transmit_packet(req,
+                                       p0 | 0x07, port->data[0],
+                                       port->data[1], 0xf7);
+                               break;
+                       }
+                       port->state = STATE_UNKNOWN;
+                       break;
+               }
+       } else if (b >= 0x80) {
+               port->data[0] = b;
+               if (b >= 0xc0 && b <= 0xdf)
+                       port->state = STATE_1PARAM;
+               else
+                       port->state = STATE_2PARAM_1;
+       } else { /* b < 0x80 */
+               switch (port->state) {
+               case STATE_1PARAM:
+                       if (port->data[0] < 0xf0) {
+                               p0 |= port->data[0] >> 4;
+                       } else {
+                               p0 |= 0x02;
+                               port->state = STATE_UNKNOWN;
+                       }
+                       gmidi_transmit_packet(req, p0, port->data[0], b, 0);
+                       break;
+               case STATE_2PARAM_1:
+                       port->data[1] = b;
+                       port->state = STATE_2PARAM_2;
+                       break;
+               case STATE_2PARAM_2:
+                       if (port->data[0] < 0xf0) {
+                               p0 |= port->data[0] >> 4;
+                               port->state = STATE_2PARAM_1;
+                       } else {
+                               p0 |= 0x03;
+                               port->state = STATE_UNKNOWN;
+                       }
+                       gmidi_transmit_packet(req,
+                               p0, port->data[0], port->data[1], b);
+                       break;
+               case STATE_SYSEX_0:
+                       port->data[0] = b;
+                       port->state = STATE_SYSEX_1;
+                       break;
+               case STATE_SYSEX_1:
+                       port->data[1] = b;
+                       port->state = STATE_SYSEX_2;
+                       break;
+               case STATE_SYSEX_2:
+                       gmidi_transmit_packet(req,
+                               p0 | 0x04, port->data[0], port->data[1], b);
+                       port->state = STATE_SYSEX_0;
+                       break;
+               }
+       }
+}
+
+static void gmidi_transmit(struct gmidi_device* dev, struct usb_request* req)
+{
+       struct usb_ep* ep = dev->in_ep;
+       struct gmidi_in_port* port = &dev->in_port;
+
+       if (!ep) {
+               return;
+       }
+       if (!req) {
+               req = alloc_ep_req(ep, buflen);
+       }
+       if (!req) {
+               ERROR(dev, "gmidi_transmit: alloc_ep_request failed\n");
+               return;
+       }
+       req->length = 0;
+       req->complete = gmidi_complete;
+
+       if (port->active) {
+               while (req->length + 3 < buflen) {
+                       uint8_t b;
+                       if (snd_rawmidi_transmit(dev->in_substream, &b, 1)
+                               != 1)
+                       {
+                               port->active = 0;
+                               break;
+                       }
+                       gmidi_transmit_byte(req, port, b);
+               }
+       }
+       if (req->length > 0) {
+               usb_ep_queue(ep, req, GFP_ATOMIC);
+       } else {
+               free_ep_req(ep, req);
+       }
+}
+
+static void gmidi_in_tasklet(unsigned long data)
+{
+       struct gmidi_device* dev = (struct gmidi_device*)data;
+
+       gmidi_transmit(dev, NULL);
+}
+
+static int gmidi_in_open(struct snd_rawmidi_substream *substream)
+{
+       struct gmidi_device* dev = substream->rmidi->private_data;
+
+       VDBG(dev, "gmidi_in_open\n");
+       dev->in_substream = substream;
+       dev->in_port.state = STATE_UNKNOWN;
+       return 0;
+}
+
+static int gmidi_in_close(struct snd_rawmidi_substream *substream)
+{
+       VDBG(dev, "gmidi_in_close\n");
+       return 0;
+}
+
+static void gmidi_in_trigger(struct snd_rawmidi_substream *substream, int up)
+{
+       struct gmidi_device* dev = substream->rmidi->private_data;
+
+       VDBG(dev, "gmidi_in_trigger %d\n", up);
+       dev->in_port.active = up;
+       if (up) {
+               tasklet_hi_schedule(&dev->tasklet);
+       }
+}
+
+static int gmidi_out_open(struct snd_rawmidi_substream *substream)
+{
+       struct gmidi_device* dev = substream->rmidi->private_data;
+
+       VDBG(dev, "gmidi_out_open\n");
+       dev->out_substream = substream;
+       return 0;
+}
+
+static int gmidi_out_close(struct snd_rawmidi_substream *substream)
+{
+       VDBG(dev, "gmidi_out_close\n");
+       return 0;
+}
+
+static void gmidi_out_trigger(struct snd_rawmidi_substream *substream, int up)
+{
+       struct gmidi_device* dev = substream->rmidi->private_data;
+
+       VDBG(dev, "gmidi_out_trigger %d\n", up);
+       if (up) {
+               set_bit(substream->number, &dev->out_triggered);
+       } else {
+               clear_bit(substream->number, &dev->out_triggered);
+       }
+}
+
+static struct snd_rawmidi_ops gmidi_in_ops = {
+       .open = gmidi_in_open,
+       .close = gmidi_in_close,
+       .trigger = gmidi_in_trigger,
+};
+
+static struct snd_rawmidi_ops gmidi_out_ops = {
+       .open = gmidi_out_open,
+       .close = gmidi_out_close,
+       .trigger = gmidi_out_trigger
+};
+
+/* register as a sound "card" */
+static int gmidi_register_card(struct gmidi_device *dev)
+{
+       struct snd_card *card;
+       struct snd_rawmidi *rmidi;
+       int err;
+       int out_ports = 1;
+       int in_ports = 1;
+       static struct snd_device_ops ops = {
+               .dev_free = gmidi_snd_free,
+       };
+
+       card = snd_card_new(index, id, THIS_MODULE, 0);
+       if (!card) {
+               ERROR(dev, "snd_card_new failed\n");
+               err = -ENOMEM;
+               goto fail;
+       }
+       dev->card = card;
+
+       err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, dev, &ops);
+       if (err < 0) {
+               ERROR(dev, "snd_device_new failed: error %d\n", err);
+               goto fail;
+       }
+
+       strcpy(card->driver, longname);
+       strcpy(card->longname, longname);
+       strcpy(card->shortname, shortname);
+
+       /* Set up rawmidi */
+       dev->in_port.dev = dev;
+       dev->in_port.active = 0;
+       snd_component_add(card, "MIDI");
+       err = snd_rawmidi_new(card, "USB MIDI Gadget", 0,
+                             out_ports, in_ports, &rmidi);
+       if (err < 0) {
+               ERROR(dev, "snd_rawmidi_new failed: error %d\n", err);
+               goto fail;
+       }
+       dev->rmidi = rmidi;
+       strcpy(rmidi->name, card->shortname);
+       rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+                           SNDRV_RAWMIDI_INFO_INPUT |
+                           SNDRV_RAWMIDI_INFO_DUPLEX;
+       rmidi->private_data = dev;
+
+       /* Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT.
+          It's an upside-down world being a gadget. */
+       snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &gmidi_in_ops);
+       snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &gmidi_out_ops);
+
+       snd_card_set_dev(card, &dev->gadget->dev);
+
+       /* register it - we're ready to go */
+       err = snd_card_register(card);
+       if (err < 0) {
+               ERROR(dev, "snd_card_register failed\n");
+               goto fail;
+       }
+
+       VDBG(dev, "gmidi_register_card finished ok\n");
+       return 0;
+
+fail:
+       if (dev->card) {
+               snd_card_free(dev->card);
+               dev->card = NULL;
+       }
+       return err;
+}
+
+/*
+ * Creates an output endpoint, and initializes output ports.
+ */
+static int __devinit gmidi_bind(struct usb_gadget *gadget)
+{
+       struct gmidi_device *dev;
+       struct usb_ep *in_ep, *out_ep;
+       int gcnum, err = 0;
+
+       /* support optional vendor/distro customization */
+       if (idVendor) {
+               if (!idProduct) {
+                       printk(KERN_ERR "idVendor needs idProduct!\n");
+                       return -ENODEV;
+               }
+               device_desc.idVendor = cpu_to_le16(idVendor);
+               device_desc.idProduct = cpu_to_le16(idProduct);
+               if (bcdDevice) {
+                       device_desc.bcdDevice = cpu_to_le16(bcdDevice);
+               }
+       }
+       if (iManufacturer) {
+               strlcpy(manufacturer, iManufacturer, sizeof(manufacturer));
+       } else {
+               snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
+                       system_utsname.sysname, system_utsname.release,
+                       gadget->name);
+       }
+       if (iProduct) {
+               strlcpy(product_desc, iProduct, sizeof(product_desc));
+       }
+       if (iSerialNumber) {
+               device_desc.iSerialNumber = STRING_SERIAL,
+               strlcpy(serial_number, iSerialNumber, sizeof(serial_number));
+       }
+
+       /* Bulk-only drivers like this one SHOULD be able to
+        * autoconfigure on any sane usb controller driver,
+        * but there may also be important quirks to address.
+        */
+       usb_ep_autoconfig_reset(gadget);
+       in_ep = usb_ep_autoconfig(gadget, &bulk_in_desc);
+       if (!in_ep) {
+autoconf_fail:
+               printk(KERN_ERR "%s: can't autoconfigure on %s\n",
+                       shortname, gadget->name);
+               return -ENODEV;
+       }
+       EP_IN_NAME = in_ep->name;
+       in_ep->driver_data = in_ep;     /* claim */
+
+       out_ep = usb_ep_autoconfig(gadget, &bulk_out_desc);
+       if (!out_ep) {
+               goto autoconf_fail;
+       }
+       EP_OUT_NAME = out_ep->name;
+       out_ep->driver_data = out_ep;   /* claim */
+
+       gcnum = usb_gadget_controller_number(gadget);
+       if (gcnum >= 0) {
+               device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
+       } else {
+               /* gmidi is so simple (no altsettings) that
+                * it SHOULD NOT have problems with bulk-capable hardware.
+                * so warn about unrecognized controllers, don't panic.
+                */
+               printk(KERN_WARNING "%s: controller '%s' not recognized\n",
+                       shortname, gadget->name);
+               device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
+       }
+
+
+       /* ok, we made sense of the hardware ... */
+       dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
+       if (!dev) {
+               return -ENOMEM;
+       }
+       spin_lock_init(&dev->lock);
+       dev->gadget = gadget;
+       dev->in_ep = in_ep;
+       dev->out_ep = out_ep;
+       set_gadget_data(gadget, dev);
+       tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev);
+
+       /* preallocate control response and buffer */
+       dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
+       if (!dev->req) {
+               err = -ENOMEM;
+               goto fail;
+       }
+       dev->req->buf = usb_ep_alloc_buffer(gadget->ep0, USB_BUFSIZ,
+                               &dev->req->dma, GFP_KERNEL);
+       if (!dev->req->buf) {
+               err = -ENOMEM;
+               goto fail;
+       }
+
+       dev->req->complete = gmidi_setup_complete;
+
+       device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
+
+       gadget->ep0->driver_data = dev;
+
+       INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname);
+       INFO(dev, "using %s, OUT %s IN %s\n", gadget->name,
+               EP_OUT_NAME, EP_IN_NAME);
+
+       /* register as an ALSA sound card */
+       err = gmidi_register_card(dev);
+       if (err < 0) {
+               goto fail;
+       }
+
+       VDBG(dev, "gmidi_bind finished ok\n");
+       return 0;
+
+fail:
+       gmidi_unbind(gadget);
+       return err;
+}
+
+
+static void gmidi_suspend(struct usb_gadget *gadget)
+{
+       struct gmidi_device *dev = get_gadget_data(gadget);
+
+       if (gadget->speed == USB_SPEED_UNKNOWN) {
+               return;
+       }
+
+       DBG(dev, "suspend\n");
+}
+
+static void gmidi_resume(struct usb_gadget *gadget)
+{
+       struct gmidi_device *dev = get_gadget_data(gadget);
+
+       DBG(dev, "resume\n");
+}
+
+
+static struct usb_gadget_driver gmidi_driver = {
+       .speed          = USB_SPEED_FULL,
+       .function       = (char *)longname,
+       .bind           = gmidi_bind,
+       .unbind         = __exit_p(gmidi_unbind),
+
+       .setup          = gmidi_setup,
+       .disconnect     = gmidi_disconnect,
+
+       .suspend        = gmidi_suspend,
+       .resume         = gmidi_resume,
+
+       .driver         = {
+               .name           = (char *)shortname,
+               .owner          = THIS_MODULE,
+       },
+};
+
+static int __init gmidi_init(void)
+{
+       return usb_gadget_register_driver(&gmidi_driver);
+}
+module_init(gmidi_init);
+
+static void __exit gmidi_cleanup(void)
+{
+       usb_gadget_unregister_driver(&gmidi_driver);
+}
+module_exit(gmidi_cleanup);
+
index 3bdc5e3ba2346a588d518339de3bc31f5834520d..4655522a08d95b10dfa227e267d3d144d3b9b694 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/compiler.h>
 #include <asm/uaccess.h>
 #include <linux/slab.h>
+#include <linux/poll.h>
 
 #include <linux/device.h>
 #include <linux/moduleparam.h>
@@ -222,7 +223,6 @@ static void put_ep (struct ep_data *data)
        /* needs no more cleanup */
        BUG_ON (!list_empty (&data->epfiles));
        BUG_ON (waitqueue_active (&data->wait));
-       BUG_ON (down_trylock (&data->lock) != 0);
        kfree (data);
 }
 
@@ -477,6 +477,10 @@ static int
 ep_release (struct inode *inode, struct file *fd)
 {
        struct ep_data          *data = fd->private_data;
+       int value;
+
+       if ((value = down_interruptible(&data->lock)) < 0)
+               return value;
 
        /* clean up if this can be reopened */
        if (data->state != STATE_EP_UNBOUND) {
@@ -485,6 +489,7 @@ ep_release (struct inode *inode, struct file *fd)
                data->hs_desc.bDescriptorType = 0;
                usb_ep_disable(data->ep);
        }
+       up (&data->lock);
        put_ep (data);
        return 0;
 }
@@ -709,7 +714,7 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o)
 /*----------------------------------------------------------------------*/
 
 /* used after endpoint configuration */
-static struct file_operations ep_io_operations = {
+static const struct file_operations ep_io_operations = {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
 
@@ -741,7 +746,7 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
        struct ep_data          *data = fd->private_data;
        struct usb_ep           *ep;
        u32                     tag;
-       int                     value;
+       int                     value, length = len;
 
        if ((value = down_interruptible (&data->lock)) < 0)
                return value;
@@ -792,7 +797,6 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                        goto fail0;
                }
        }
-       value = len;
 
        spin_lock_irq (&data->dev->lock);
        if (data->dev->state == STATE_DEV_UNBOUND) {
@@ -822,8 +826,10 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
                                data->name);
                data->state = STATE_EP_DEFER_ENABLE;
        }
-       if (value == 0)
+       if (value == 0) {
                fd->f_op = &ep_io_operations;
+               value = length;
+       }
 gone:
        spin_unlock_irq (&data->dev->lock);
        if (value < 0) {
@@ -844,7 +850,7 @@ fail1:
 static int
 ep_open (struct inode *inode, struct file *fd)
 {
-       struct ep_data          *data = inode->u.generic_ip;
+       struct ep_data          *data = inode->i_private;
        int                     value = -EBUSY;
 
        if (down_interruptible (&data->lock) != 0)
@@ -867,7 +873,7 @@ ep_open (struct inode *inode, struct file *fd)
 }
 
 /* used before endpoint configuration */
-static struct file_operations ep_config_operations = {
+static const struct file_operations ep_config_operations = {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
 
@@ -1009,7 +1015,7 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
                        else {
                                len = min (len, (size_t)dev->req->actual);
 // FIXME don't call this with the spinlock held ...
-                               if (copy_to_user (buf, &dev->req->buf, len))
+                               if (copy_to_user (buf, dev->req->buf, len))
                                        retval = -EFAULT;
                                clean_req (dev->gadget->ep0, dev->req);
                                /* NOTE userspace can't yet choose to stall */
@@ -1229,6 +1235,35 @@ dev_release (struct inode *inode, struct file *fd)
        return 0;
 }
 
+static unsigned int
+ep0_poll (struct file *fd, poll_table *wait)
+{
+       struct dev_data         *dev = fd->private_data;
+       int                     mask = 0;
+
+       poll_wait(fd, &dev->wait, wait);
+
+       spin_lock_irq (&dev->lock);
+
+       /* report fd mode change before acting on it */
+       if (dev->setup_abort) {
+               dev->setup_abort = 0;
+               mask = POLLHUP;
+               goto out;
+       }
+
+       if (dev->state == STATE_SETUP) {
+               if (dev->setup_in || dev->setup_can_stall)
+                       mask = POLLOUT;
+       } else {
+               if (dev->ev_next != 0)
+                       mask = POLLIN;
+       }
+out:
+       spin_unlock_irq(&dev->lock);
+       return mask;
+}
+
 static int dev_ioctl (struct inode *inode, struct file *fd,
                unsigned code, unsigned long value)
 {
@@ -1241,14 +1276,14 @@ static int dev_ioctl (struct inode *inode, struct file *fd,
 }
 
 /* used after device configuration */
-static struct file_operations ep0_io_operations = {
+static const struct file_operations ep0_io_operations = {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
 
        .read =         ep0_read,
        .write =        ep0_write,
        .fasync =       ep0_fasync,
-       // .poll =      ep0_poll,
+       .poll =         ep0_poll,
        .ioctl =        dev_ioctl,
        .release =      dev_release,
 };
@@ -1696,16 +1731,17 @@ gadgetfs_disconnect (struct usb_gadget *gadget)
 {
        struct dev_data         *dev = get_gadget_data (gadget);
 
+       spin_lock (&dev->lock);
        if (dev->state == STATE_UNCONNECTED) {
                DBG (dev, "already unconnected\n");
-               return;
+               goto exit;
        }
        dev->state = STATE_UNCONNECTED;
 
        INFO (dev, "disconnected\n");
-       spin_lock (&dev->lock);
        next_event (dev, GADGETFS_DISCONNECT);
        ep0_readable (dev);
+exit:
        spin_unlock (&dev->lock);
 }
 
@@ -1909,7 +1945,7 @@ fail:
 static int
 dev_open (struct inode *inode, struct file *fd)
 {
-       struct dev_data         *dev = inode->u.generic_ip;
+       struct dev_data         *dev = inode->i_private;
        int                     value = -EBUSY;
 
        if (dev->state == STATE_DEV_DISABLED) {
@@ -1922,7 +1958,7 @@ dev_open (struct inode *inode, struct file *fd)
        return value;
 }
 
-static struct file_operations dev_init_operations = {
+static const struct file_operations dev_init_operations = {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
 
@@ -1966,11 +2002,10 @@ gadgetfs_make_inode (struct super_block *sb,
                inode->i_mode = mode;
                inode->i_uid = default_uid;
                inode->i_gid = default_gid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime
                                = CURRENT_TIME;
-               inode->u.generic_ip = data;
+               inode->i_private = data;
                inode->i_fop = fops;
        }
        return inode;
index 09243239d948cf4c034515c89838b41b769b7817..3bda37f9a35f7d54ebf254de672bc44d44e1027d 100644 (file)
@@ -2,7 +2,7 @@
  * Driver for the PLX NET2280 USB device controller.
  * Specs and errata are available from <http://www.plxtech.com>.
  *
- * PLX Technology Inc. (formerly NetChip Technology) supported the 
+ * PLX Technology Inc. (formerly NetChip Technology) supported the
  * development of this driver.
  *
  *
@@ -26,7 +26,8 @@
  * Copyright (C) 2003 David Brownell
  * Copyright (C) 2003-2005 PLX Technology, Inc.
  *
- * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility with 2282 chip
+ * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility
+ *     with 2282 chip
  *
  * 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
@@ -85,7 +86,7 @@ static const char driver_name [] = "net2280";
 static const char driver_desc [] = DRIVER_DESC;
 
 static const char ep0name [] = "ep0";
-static const char *ep_name [] = {
+static const char *const ep_name [] = {
        ep0name,
        "ep-a", "ep-b", "ep-c", "ep-d",
        "ep-e", "ep-f",
@@ -225,7 +226,9 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
        if (!ep->is_in)
                writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
        else if (dev->pdev->device != 0x2280) {
-               /* Added for 2282, Don't use nak packets on an in endpoint, this was ignored on 2280 */
+               /* Added for 2282, Don't use nak packets on an in endpoint,
+                * this was ignored on 2280
+                */
                writel ((1 << CLEAR_NAK_OUT_PACKETS)
                        | (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
        }
@@ -288,7 +291,7 @@ static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec)
        return -ETIMEDOUT;
 }
 
-static struct usb_ep_ops net2280_ep_ops;
+static const struct usb_ep_ops net2280_ep_ops;
 
 static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
 {
@@ -449,34 +452,15 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req)
 
 /*-------------------------------------------------------------------------*/
 
-#undef USE_KMALLOC
-
-/* many common platforms have dma-coherent caches, which means that it's
- * safe to use kmalloc() memory for all i/o buffers without using any
- * cache flushing calls.  (unless you're trying to share cache lines
- * between dma and non-dma activities, which is a slow idea in any case.)
+/*
+ * dma-coherent memory allocation (for dma-capable endpoints)
  *
- * other platforms need more care, with 2.5 having a moderately general
- * solution (which falls down for allocations smaller than one page)
- * that improves significantly on the 2.4 PCI allocators by removing
- * the restriction that memory never be freed in_interrupt().
+ * NOTE: the dma_*_coherent() API calls suck.  Most implementations are
+ * (a) page-oriented, so small buffers lose big; and (b) asymmetric with
+ * respect to calls with irqs disabled:  alloc is safe, free is not.
+ * We currently work around (b), but not (a).
  */
-#if    defined(CONFIG_X86)
-#define USE_KMALLOC
-
-#elif  defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
-#define USE_KMALLOC
 
-#elif  defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT)
-#define USE_KMALLOC
-
-/* FIXME there are other cases, including an x86-64 one ...  */
-#endif
-
-/* allocating buffers this way eliminates dma mapping overhead, which
- * on some platforms will mean eliminating a per-io buffer copy.  with
- * some kinds of system caches, further tweaks may still be needed.
- */
 static void *
 net2280_alloc_buffer (
        struct usb_ep           *_ep,
@@ -493,43 +477,71 @@ net2280_alloc_buffer (
                return NULL;
        *dma = DMA_ADDR_INVALID;
 
-#if    defined(USE_KMALLOC)
-       retval = kmalloc(bytes, gfp_flags);
-       if (retval)
-               *dma = virt_to_phys(retval);
-#else
-       if (ep->dma) {
-               /* the main problem with this call is that it wastes memory
-                * on typical 1/N page allocations: it allocates 1-N pages.
-                */
-#warning Using dma_alloc_coherent even with buffers smaller than a page.
+       if (ep->dma)
                retval = dma_alloc_coherent(&ep->dev->pdev->dev,
                                bytes, dma, gfp_flags);
-       else
+       else
                retval = kmalloc(bytes, gfp_flags);
-#endif
        return retval;
 }
 
+static DEFINE_SPINLOCK(buflock);
+static LIST_HEAD(buffers);
+
+struct free_record {
+       struct list_head        list;
+       struct device           *dev;
+       unsigned                bytes;
+       dma_addr_t              dma;
+};
+
+static void do_free(unsigned long ignored)
+{
+       spin_lock_irq(&buflock);
+       while (!list_empty(&buffers)) {
+               struct free_record      *buf;
+
+               buf = list_entry(buffers.next, struct free_record, list);
+               list_del(&buf->list);
+               spin_unlock_irq(&buflock);
+
+               dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma);
+
+               spin_lock_irq(&buflock);
+       }
+       spin_unlock_irq(&buflock);
+}
+
+static DECLARE_TASKLET(deferred_free, do_free, 0);
+
 static void
 net2280_free_buffer (
        struct usb_ep *_ep,
-       void *buf,
+       void *address,
        dma_addr_t dma,
        unsigned bytes
 ) {
        /* free memory into the right allocator */
-#ifndef        USE_KMALLOC
        if (dma != DMA_ADDR_INVALID) {
                struct net2280_ep       *ep;
+               struct free_record      *buf = address;
+               unsigned long           flags;
 
                ep = container_of(_ep, struct net2280_ep, ep);
                if (!_ep)
                        return;
-               dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma);
+
+               ep = container_of (_ep, struct net2280_ep, ep);
+               buf->dev = &ep->dev->pdev->dev;
+               buf->bytes = bytes;
+               buf->dma = dma;
+
+               spin_lock_irqsave(&buflock, flags);
+               list_add_tail(&buf->list, &buffers);
+               tasklet_schedule(&deferred_free);
+               spin_unlock_irqrestore(&buflock, flags);
        } else
-#endif
-               kfree (buf);
+               kfree (address);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -737,7 +749,8 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
         */
        if (ep->is_in)
                dmacount |= (1 << DMA_DIRECTION);
-       if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280)
+       if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0)
+                       || ep->dev->pdev->device != 0x2280)
                dmacount |= (1 << END_OF_CHAIN);
 
        req->valid = valid;
@@ -812,7 +825,7 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
 
        /* previous OUT packet might have been short */
        if (!ep->is_in && ((tmp = readl (&ep->regs->ep_stat))
-                               & (1 << NAK_OUT_PACKETS)) != 0) {
+                               & (1 << NAK_OUT_PACKETS)) != 0) {
                writel ((1 << SHORT_PACKET_TRANSFERRED_INTERRUPT),
                        &ep->regs->ep_stat);
 
@@ -1373,7 +1386,7 @@ net2280_fifo_flush (struct usb_ep *_ep)
        (void) readl (&ep->regs->ep_rsp);
 }
 
-static struct usb_ep_ops net2280_ep_ops = {
+static const struct usb_ep_ops net2280_ep_ops = {
        .enable         = net2280_enable,
        .disable        = net2280_disable,
 
@@ -1631,7 +1644,7 @@ show_registers (struct device *_dev, struct device_attribute *attr, char *buf)
        }
 
        /* Indexed Registers */
-               // none yet 
+               // none yet
 
        /* Statistics */
        t = scnprintf (next, size, "\nirqs:  ");
@@ -1691,11 +1704,11 @@ show_queues (struct device *_dev, struct device_attribute *attr, char *buf)
                                ({ char *val;
                                 switch (d->bmAttributes & 0x03) {
                                 case USB_ENDPOINT_XFER_BULK:
-                                       val = "bulk"; break;
+                                       val = "bulk"; break;
                                 case USB_ENDPOINT_XFER_INT:
-                                       val = "intr"; break;
+                                       val = "intr"; break;
                                 default:
-                                       val = "iso"; break;
+                                       val = "iso"; break;
                                 }; val; }),
                                le16_to_cpu (d->wMaxPacketSize) & 0x1fff,
                                ep->dma ? "dma" : "pio", ep->fifo_size
@@ -1808,8 +1821,8 @@ extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
  * net2280_set_fifo_mode - change allocation of fifo buffers
  * @gadget: access to the net2280 device that will be updated
  * @mode: 0 for default, four 1kB buffers (ep-a through ep-d);
- *     1 for two 2kB buffers (ep-a and ep-b only);
- *     2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c).
+ *     1 for two 2kB buffers (ep-a and ep-b only);
+ *     2 for one 2kB buffer (ep-a) and two 1kB ones (ep-b, ep-c).
  *
  * returns zero on success, else negative errno.  when this succeeds,
  * the contents of gadget->ep_list may have changed.
@@ -2241,7 +2254,8 @@ static void handle_ep_small (struct net2280_ep *ep)
                                req->td->dmacount = 0;
                                t = readl (&ep->regs->ep_avail);
                                dma_done (ep, req, count,
-                                       (ep->out_overflow || t) ? -EOVERFLOW : 0);
+                                       (ep->out_overflow || t)
+                                               ? -EOVERFLOW : 0);
                        }
 
                        /* also flush to prevent erratum 0106 trouble */
@@ -2411,7 +2425,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                        , &ep->regs->ep_stat);
                u.raw [0] = readl (&dev->usb->setup0123);
                u.raw [1] = readl (&dev->usb->setup4567);
-               
+
                cpu_to_le32s (&u.raw [0]);
                cpu_to_le32s (&u.raw [1]);
 
@@ -2578,14 +2592,16 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
 
        /* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
         * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and
-        * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT 
+        * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
         * only indicates a change in the reset state).
         */
        if (stat & tmp) {
                writel (tmp, &dev->regs->irqstat1);
-               if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) && 
-                               ((readl (&dev->usb->usbstat) & mask) == 0))
-                               || ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0) 
+               if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT))
+                                       && ((readl (&dev->usb->usbstat) & mask)
+                                                       == 0))
+                               || ((readl (&dev->usb->usbctl)
+                                       & (1 << VBUS_PIN)) == 0)
                            ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
                        DEBUG (dev, "disconnect %s\n",
                                        dev->driver->driver.name);
@@ -2852,7 +2868,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 
        /* now all the pci goodies ... */
        if (pci_enable_device (pdev) < 0) {
-               retval = -ENODEV;
+               retval = -ENODEV;
                goto done;
        }
        dev->enabled = 1;
@@ -2870,6 +2886,10 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
        }
        dev->region = 1;
 
+       /* FIXME provide firmware download interface to put
+        * 8051 code into the chip, e.g. to turn on PCI PM.
+        */
+
        base = ioremap_nocache (resource, len);
        if (base == NULL) {
                DEBUG (dev, "can't map memory\n");
@@ -2984,16 +3004,16 @@ static void net2280_shutdown (struct pci_dev *pdev)
 
 /*-------------------------------------------------------------------------*/
 
-static struct pci_device_id pci_ids [] = { {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
+static const struct pci_device_id pci_ids [] = { {
+       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class_mask =   ~0,
        .vendor =       0x17cc,
        .device =       0x2280,
        .subvendor =    PCI_ANY_ID,
        .subdevice =    PCI_ANY_ID,
 }, {
-       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
-       .class_mask =   ~0,
+       .class =        ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
+       .class_mask =   ~0,
        .vendor =       0x17cc,
        .device =       0x2282,
        .subvendor =    PCI_ANY_ID,
index 2de9748ee6734c7763a2e4618f9769c91d36bce2..0a64504c2545467409a2ebcae606c2e151f9a95f 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/platform_device.h>
 #include <linux/usb_ch9.h>
 #include <linux/usb_gadget.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 #include <linux/dma-mapping.h>
 
 #include <asm/byteorder.h>
@@ -2437,7 +2437,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
        return single_open(file, proc_udc_show, NULL);
 }
 
-static struct file_operations proc_ops = {
+static const struct file_operations proc_ops = {
        .open           = proc_udc_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
index fff027d30a09d2e564f842baa4eba11a90a80ad2..f1adcf8b202307f4d6bf0c1b4d373541ccc4ab14 100644 (file)
@@ -150,6 +150,39 @@ MODULE_PARM_DESC (fifo_mode, "pxa2xx udc fifo mode");
 static void pxa2xx_ep_fifo_flush (struct usb_ep *ep);
 static void nuke (struct pxa2xx_ep *, int status);
 
+/* one GPIO should be used to detect VBUS from the host */
+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);
+       if (mach->udc_is_connected)
+               return mach->udc_is_connected();
+       return 1;
+}
+
+/* one GPIO should control a D+ pullup, so host sees this device (or not) */
+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);
+       else if (mach->udc_command)
+               mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
+}
+
+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);
+       else if (mach->udc_command)
+               mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+}
+
 static void pio_irq_enable(int bEndpointAddress)
 {
         bEndpointAddress &= 0xf;
@@ -1721,6 +1754,16 @@ lubbock_vbus_irq(int irq, void *_dev, struct pt_regs *r)
 
 #endif
 
+static irqreturn_t
+udc_vbus_irq(int irq, void *_dev, struct pt_regs *r)
+{
+       struct pxa2xx_udc       *dev = _dev;
+       int                     vbus = pxa_gpio_get(dev->mach->gpio_vbus);
+
+       pxa2xx_udc_vbus_session(&dev->gadget, vbus);
+       return IRQ_HANDLED;
+}
+
 
 /*-------------------------------------------------------------------------*/
 
@@ -2438,7 +2481,7 @@ static struct pxa2xx_udc memory = {
 static int __init pxa2xx_udc_probe(struct platform_device *pdev)
 {
        struct pxa2xx_udc *dev = &memory;
-       int retval, out_dma = 1;
+       int retval, out_dma = 1, vbus_irq;
        u32 chiprev;
 
        /* insist on Intel/ARM/XScale */
@@ -2502,6 +2545,16 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
        /* other non-static parts of init */
        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);
+               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);
 
        init_timer(&dev->timer);
        dev->timer.function = udc_watchdog;
@@ -2557,8 +2610,19 @@ lubbock_fail0:
                HEX_DISPLAY(dev->stats.irqs);
                LUB_DISC_BLNK_LED &= 0xff;
 #endif
-       }
+       } else
 #endif
+       if (vbus_irq) {
+               retval = request_irq(vbus_irq, udc_vbus_irq,
+                               SA_INTERRUPT | SA_SAMPLE_RANDOM,
+                               driver_name, dev);
+               if (retval != 0) {
+                       printk(KERN_ERR "%s: can't get irq %i, err %d\n",
+                               driver_name, vbus_irq, retval);
+                       free_irq(IRQ_USB, dev);
+                       return -EBUSY;
+               }
+       }
        create_proc_files();
 
        return 0;
@@ -2587,6 +2651,8 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev)
                free_irq(LUBBOCK_USB_IRQ, dev);
        }
 #endif
+       if (dev->mach->gpio_vbus)
+               free_irq(IRQ_GPIO(dev->mach->gpio_vbus), dev);
        platform_set_drvdata(pdev, NULL);
        the_controller = NULL;
        return 0;
index 19a883f7d1b8f610c8c9c3a0cba195aeacc88836..8e598c8bf4e388da20c6672b3a0f54a95e296e6e 100644 (file)
@@ -177,27 +177,19 @@ struct pxa2xx_udc {
 
 static struct pxa2xx_udc *the_controller;
 
-/* one GPIO should be used to detect VBUS from the host */
-static inline int is_vbus_present(void)
+static inline int pxa_gpio_get(unsigned gpio)
 {
-       if (!the_controller->mach->udc_is_connected)
-               return 1;
-       return the_controller->mach->udc_is_connected();
+       return (GPLR(gpio) & GPIO_bit(gpio)) != 0;
 }
 
-/* one GPIO should control a D+ pullup, so host sees this device (or not) */
-static inline void pullup_off(void)
+static inline void pxa_gpio_set(unsigned gpio, int is_on)
 {
-       if (!the_controller->mach->udc_command)
-               return;
-       the_controller->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT);
-}
+       int mask = GPIO_bit(gpio);
 
-static inline void pullup_on(void)
-{
-       if (!the_controller->mach->udc_command)
-               return;
-       the_controller->mach->udc_command(PXA2XX_UDC_CMD_CONNECT);
+       if (is_on)
+               GPSR(gpio) = mask;
+       else
+               GPCR(gpio) = mask;
 }
 
 /*-------------------------------------------------------------------------*/
index e762aa19ab0a1c9fef4a87a105b0221b95e3ddad..b893e3118e1be480e9b4d8bbd739152efd718141 100644 (file)
@@ -1120,12 +1120,15 @@ static int gs_send(struct gs_dev *dev)
 gs_debug_level(3, "gs_send: len=%d, 0x%2.2x 0x%2.2x 0x%2.2x ...\n", len, *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2));
                        list_del(&req_entry->re_entry);
                        req->length = len;
+                       spin_unlock_irqrestore(&dev->dev_lock, flags);
                        if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
                                printk(KERN_ERR
                                "gs_send: cannot queue read request, ret=%d\n",
                                        ret);
+                               spin_lock_irqsave(&dev->dev_lock, flags);
                                break;
                        }
+                       spin_lock_irqsave(&dev->dev_lock, flags);
                } else {
                        break;
                }
index b93d71d28db7a04a011735318973181e953eedbf..cf10cbc98f8089885ab3174ceb09e56c369aa543 100644 (file)
@@ -83,6 +83,7 @@ config USB_OHCI_HCD
        tristate "OHCI HCD support"
        depends on USB && USB_ARCH_HAS_OHCI
        select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
+       select I2C if ARCH_PNX4008
        ---help---
          The Open Host Controller Interface (OHCI) is a standard for accessing
          USB 1.1 host controller hardware.  It does more in hardware than Intel's
@@ -141,6 +142,34 @@ config USB_UHCI_HCD
          To compile this driver as a module, choose M here: the
          module will be called uhci-hcd.
 
+config USB_U132_HCD
+       tristate "Elan U132 Adapter Host Controller"
+       depends on USB && USB_FTDI_ELAN
+       default M
+       help
+         The U132 adapter is a USB to CardBus adapter specifically designed
+         for PC cards that contain an OHCI host controller. Typical PC cards
+         are the Orange Mobile 3G Option GlobeTrotter Fusion card. The U132
+         adapter will *NOT* work with PC cards that do not contain an OHCI
+         controller.
+
+         For those PC cards that contain multiple OHCI controllers only ther
+         first one is used.
+
+         The driver consists of two modules, the "ftdi-elan" module is a
+         USB client driver that interfaces to the FTDI chip within ELAN's
+         USB-to-PCMCIA adapter, and this "u132-hcd" module is a USB host
+         controller driver that talks to the OHCI controller within the
+         CardBus cards that are inserted in the U132 adapter.
+
+         This driver has been tested with a CardBus OHCI USB adapter, and
+         worked with a USB PEN Drive inserted into the first USB port of
+         the PCCARD. A rather pointless thing to do, but useful for testing.
+
+         It is safe to say M here.
+
+         See also <http://www.elandigitalsystems.com/support/ufaq/u132linux.php>
+
 config USB_SL811_HCD
        tristate "SL811HS HCD support"
        depends on USB
index e3020f4b17be9a4ea8572768d234ac9301da33f3..a2e58c86849fc597972e4cb675eb9a813dff12f8 100644 (file)
@@ -14,4 +14,5 @@ obj-$(CONFIG_USB_OHCI_HCD)    += ohci-hcd.o
 obj-$(CONFIG_USB_UHCI_HCD)     += uhci-hcd.o
 obj-$(CONFIG_USB_SL811_HCD)    += sl811-hcd.o
 obj-$(CONFIG_USB_SL811_CS)     += sl811_cs.o
+obj-$(CONFIG_USB_U132_HCD)     += u132-hcd.o
 obj-$(CONFIG_ETRAX_ARCH_V10)   += hc_crisv10.o
index 26ed757d22a66139ea500eaddc1130f4eeb2baf4..5d1b12aad7766acc39d338c9200dfc4ca6b86601 100644 (file)
@@ -200,6 +200,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
        .reset = ehci_init,
        .start = ehci_run,
        .stop = ehci_stop,
+       .shutdown = ehci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -268,6 +269,7 @@ MODULE_ALIAS("au1xxx-ehci");
 static struct platform_driver ehci_hcd_au1xxx_driver = {
        .probe = ehci_hcd_au1xxx_drv_probe,
        .remove = ehci_hcd_au1xxx_drv_remove,
+       .shutdown = usb_hcd_platform_shutdown,
        /*.suspend      = ehci_hcd_au1xxx_drv_suspend, */
        /*.resume       = ehci_hcd_au1xxx_drv_resume, */
        .driver = {
index 65ac9fef3a7c1dfc382ef2c8aaf5a089fdb7a7ad..23b95b2bfe1572e7788a6422e4a09f3a60261d2e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2001-2002 by David Brownell
- * 
+ *
  * 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
@@ -65,7 +65,7 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label)
                for (i = 0; i < HCS_N_PORTS (params); i++) {
                        // FIXME MIPS won't readb() ...
                        byte = readb (&ehci->caps->portroute[(i>>1)]);
-                       sprintf(tmp, "%d ", 
+                       sprintf(tmp, "%d ",
                                ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf)));
                        strcat(buf, tmp);
                }
@@ -141,12 +141,12 @@ dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh)
 }
 
 static void __attribute__((__unused__))
-dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) 
+dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
 {
        ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n",
                label, itd->frame, itd, le32_to_cpu(itd->hw_next), itd->urb);
        ehci_dbg (ehci,
-               "  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", 
+               "  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
                le32_to_cpu(itd->hw_transaction[0]),
                le32_to_cpu(itd->hw_transaction[1]),
                le32_to_cpu(itd->hw_transaction[2]),
@@ -156,7 +156,7 @@ dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
                le32_to_cpu(itd->hw_transaction[6]),
                le32_to_cpu(itd->hw_transaction[7]));
        ehci_dbg (ehci,
-               "  buf:   %08x %08x %08x %08x %08x %08x %08x\n", 
+               "  buf:   %08x %08x %08x %08x %08x %08x %08x\n",
                le32_to_cpu(itd->hw_bufp[0]),
                le32_to_cpu(itd->hw_bufp[1]),
                le32_to_cpu(itd->hw_bufp[2]),
@@ -171,12 +171,12 @@ dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
 }
 
 static void __attribute__((__unused__))
-dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) 
+dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd)
 {
        ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n",
                label, sitd->frame, sitd, le32_to_cpu(sitd->hw_next), sitd->urb);
        ehci_dbg (ehci,
-               "  addr %08x sched %04x result %08x buf %08x %08x\n", 
+               "  addr %08x sched %04x result %08x buf %08x %08x\n",
                le32_to_cpu(sitd->hw_fullspeed_ep),
                le32_to_cpu(sitd->hw_uframe),
                le32_to_cpu(sitd->hw_results),
@@ -451,7 +451,7 @@ show_async (struct class_device *class_dev, char *buf)
        *buf = 0;
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ehci = hcd_to_ehci (hcd);
        next = buf;
        size = PAGE_SIZE;
@@ -497,7 +497,7 @@ show_periodic (struct class_device *class_dev, char *buf)
        seen_count = 0;
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ehci = hcd_to_ehci (hcd);
        next = buf;
        size = PAGE_SIZE;
@@ -634,7 +634,7 @@ show_registers (struct class_device *class_dev, char *buf)
        static char             label [] = "";
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ehci = hcd_to_ehci (hcd);
        next = buf;
        size = PAGE_SIZE;
@@ -754,9 +754,7 @@ show_registers (struct class_device *class_dev, char *buf)
        }
 
        if (ehci->reclaim) {
-               temp = scnprintf (next, size, "reclaim qh %p%s\n",
-                               ehci->reclaim,
-                               ehci->reclaim_ready ? " ready" : "");
+               temp = scnprintf (next, size, "reclaim qh %p\n", ehci->reclaim);
                size -= temp;
                next += temp;
        }
@@ -785,10 +783,11 @@ static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 static inline void create_debug_files (struct ehci_hcd *ehci)
 {
        struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
+       int retval;
 
-       class_device_create_file(cldev, &class_device_attr_async);
-       class_device_create_file(cldev, &class_device_attr_periodic);
-       class_device_create_file(cldev, &class_device_attr_registers);
+       retval = class_device_create_file(cldev, &class_device_attr_async);
+       retval = class_device_create_file(cldev, &class_device_attr_periodic);
+       retval = class_device_create_file(cldev, &class_device_attr_registers);
 }
 
 static inline void remove_debug_files (struct ehci_hcd *ehci)
index d030516edfb9f6077003d7b553ee3d52a0805580..1a915e982c1c49a9c671d2769f23fad04f6909a1 100644 (file)
@@ -285,6 +285,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
        .resume = ehci_bus_resume,
 #endif
        .stop = ehci_stop,
+       .shutdown = ehci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -329,6 +330,7 @@ MODULE_ALIAS("fsl-ehci");
 static struct platform_driver ehci_fsl_driver = {
        .probe = ehci_fsl_drv_probe,
        .remove = ehci_fsl_drv_remove,
+       .shutdown = usb_hcd_platform_shutdown,
        .driver = {
                   .name = "fsl-ehci",
                   },
index d63177a8eaea330b41e6465f740efa4d7b3ba3c7..5ac918591131a5a11e08d75bc87a7d1d40363aec 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2000-2004 by David Brownell
- * 
+ *
  * 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
@@ -70,7 +70,7 @@
  * 2002-08-06  Handling for bulk and interrupt transfers is mostly shared;
  *     only scheduling is different, no arbitrary limitations.
  * 2002-07-25  Sanity check PCI reads, mostly for better cardbus support,
- *     clean up HC run state handshaking.
+ *     clean up HC run state handshaking.
  * 2002-05-24  Preliminary FS/LS interrupts, using scheduling shortcuts
  * 2002-05-11  Clear TT errors for FS/LS ctrl/bulk.  Fill in some other
  *     missing pieces:  enabling 64bit dma, handoff from BIOS/SMM.
@@ -111,7 +111,7 @@ static const char   hcd_name [] = "ehci_hcd";
 #define        EHCI_TUNE_MULT_TT       1
 #define        EHCI_TUNE_FLS           2       /* (small) 256 frame schedule */
 
-#define EHCI_IAA_JIFFIES       (HZ/100)        /* arbitrary; ~10 msec */
+#define EHCI_IAA_MSECS         10              /* arbitrary */
 #define EHCI_IO_JIFFIES                (HZ/10)         /* io watchdog > irq_thresh */
 #define EHCI_ASYNC_JIFFIES     (HZ/20)         /* async idle timeout */
 #define EHCI_SHRINK_JIFFIES    (HZ/200)        /* async qh unlink delay */
@@ -254,6 +254,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
 
 /*-------------------------------------------------------------------------*/
 
+static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs);
 static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs);
 
 #include "ehci-hub.c"
@@ -263,28 +264,39 @@ static void ehci_work(struct ehci_hcd *ehci, struct pt_regs *regs);
 
 /*-------------------------------------------------------------------------*/
 
-static void ehci_watchdog (unsigned long param)
+static void ehci_iaa_watchdog (unsigned long param)
 {
        struct ehci_hcd         *ehci = (struct ehci_hcd *) param;
        unsigned long           flags;
+       u32                     status;
 
        spin_lock_irqsave (&ehci->lock, flags);
+       WARN_ON(!ehci->reclaim);
 
-       /* lost IAA irqs wedge things badly; seen with a vt8235 */
+       /* lost IAA irqs wedge things badly; seen first with a vt8235 */
        if (ehci->reclaim) {
-               u32             status = readl (&ehci->regs->status);
-
+               status = readl (&ehci->regs->status);
                if (status & STS_IAA) {
                        ehci_vdbg (ehci, "lost IAA\n");
                        COUNT (ehci->stats.lost_iaa);
                        writel (STS_IAA, &ehci->regs->status);
-                       ehci->reclaim_ready = 1;
+                       end_unlink_async (ehci, NULL);
                }
        }
 
-       /* stop async processing after it's idled a bit */
+       spin_unlock_irqrestore (&ehci->lock, flags);
+}
+
+static void ehci_watchdog (unsigned long param)
+{
+       struct ehci_hcd         *ehci = (struct ehci_hcd *) param;
+       unsigned long           flags;
+
+       spin_lock_irqsave (&ehci->lock, flags);
+
+       /* stop async processing after it's idled a bit */
        if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
-               start_unlink_async (ehci, ehci->async);
+               start_unlink_async (ehci, ehci->async);
 
        /* ehci could run by timer, without IRQs ... */
        ehci_work (ehci, NULL);
@@ -292,21 +304,20 @@ static void ehci_watchdog (unsigned long param)
        spin_unlock_irqrestore (&ehci->lock, flags);
 }
 
-/* Reboot notifiers kick in for silicon on any bus (not just pci, etc).
+/* 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.
  */
-static int
-ehci_reboot (struct notifier_block *self, unsigned long code, void *null)
+static void
+ehci_shutdown (struct usb_hcd *hcd)
 {
-       struct ehci_hcd         *ehci;
+       struct ehci_hcd *ehci;
 
-       ehci = container_of (self, struct ehci_hcd, reboot_notifier);
+       ehci = hcd_to_ehci (hcd);
        (void) ehci_halt (ehci);
 
        /* make BIOS/etc use companion controller during reboot */
        writel (0, &ehci->regs->configured_flag);
-       return 0;
 }
 
 static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
@@ -334,8 +345,6 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
 static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
        timer_action_done (ehci, TIMER_IO_WATCHDOG);
-       if (ehci->reclaim_ready)
-               end_unlink_async (ehci, regs);
 
        /* another CPU may drop ehci->lock during a schedule scan while
         * it reports urb completions.  this flag guards against bogus
@@ -370,6 +379,7 @@ static void ehci_stop (struct usb_hcd *hcd)
 
        /* no more interrupts ... */
        del_timer_sync (&ehci->watchdog);
+       del_timer_sync (&ehci->iaa_watchdog);
 
        spin_lock_irq(&ehci->lock);
        if (HC_IS_RUNNING (hcd->state))
@@ -381,7 +391,6 @@ static void ehci_stop (struct usb_hcd *hcd)
 
        /* let companion controllers work when we aren't */
        writel (0, &ehci->regs->configured_flag);
-       unregister_reboot_notifier (&ehci->reboot_notifier);
 
        remove_debug_files (ehci);
 
@@ -417,6 +426,10 @@ static int ehci_init(struct usb_hcd *hcd)
        ehci->watchdog.function = ehci_watchdog;
        ehci->watchdog.data = (unsigned long) ehci;
 
+       init_timer(&ehci->iaa_watchdog);
+       ehci->iaa_watchdog.function = ehci_iaa_watchdog;
+       ehci->iaa_watchdog.data = (unsigned long) ehci;
+
        /*
         * hw default: 1K periodic list heads, one per frame.
         * periodic_size can shrink by USBCMD update if hcc_params allows.
@@ -427,13 +440,12 @@ static int ehci_init(struct usb_hcd *hcd)
 
        /* controllers may cache some of the periodic schedule ... */
        hcc_params = readl(&ehci->caps->hcc_params);
-       if (HCC_ISOC_CACHE(hcc_params))         // full frame cache
+       if (HCC_ISOC_CACHE(hcc_params))         // full frame cache
                ehci->i_thresh = 8;
        else                                    // N microframes cached
                ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 
        ehci->reclaim = NULL;
-       ehci->reclaim_ready = 0;
        ehci->next_uframe = -1;
 
        /*
@@ -483,9 +495,6 @@ static int ehci_init(struct usb_hcd *hcd)
        }
        ehci->command = temp;
 
-       ehci->reboot_notifier.notifier_call = ehci_reboot;
-       register_reboot_notifier(&ehci->reboot_notifier);
-
        return 0;
 }
 
@@ -499,7 +508,6 @@ static int ehci_run (struct usb_hcd *hcd)
 
        /* EHCI spec section 4.1 */
        if ((retval = ehci_reset(ehci)) != 0) {
-               unregister_reboot_notifier(&ehci->reboot_notifier);
                ehci_mem_cleanup(ehci);
                return retval;
        }
@@ -611,7 +619,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
        /* complete the unlinking of some qh [4.15.2.3] */
        if (status & STS_IAA) {
                COUNT (ehci->stats.reclaim);
-               ehci->reclaim_ready = 1;
+               end_unlink_async (ehci, regs);
                bh = 1;
        }
 
@@ -715,10 +723,14 @@ static int ehci_urb_enqueue (
 
 static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-       /* if we need to use IAA and it's busy, defer */
-       if (qh->qh_state == QH_STATE_LINKED
-                       && ehci->reclaim
-                       && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
+       // BUG_ON(qh->qh_state != QH_STATE_LINKED);
+
+       /* failfast */
+       if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
+               end_unlink_async (ehci, NULL);
+
+       /* defer till later if busy */
+       else if (ehci->reclaim) {
                struct ehci_qh          *last;
 
                for (last = ehci->reclaim;
@@ -728,12 +740,8 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
                qh->qh_state = QH_STATE_UNLINK_WAIT;
                last->reclaim = qh;
 
-       /* bypass IAA if the hc can't care */
-       } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
-               end_unlink_async (ehci, NULL);
-
-       /* something else might have unlinked the qh by now */
-       if (qh->qh_state == QH_STATE_LINKED)
+       /* start IAA cycle */
+       } else
                start_unlink_async (ehci, qh);
 }
 
@@ -755,7 +763,19 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
                qh = (struct ehci_qh *) urb->hcpriv;
                if (!qh)
                        break;
-               unlink_async (ehci, qh);
+               switch (qh->qh_state) {
+               case QH_STATE_LINKED:
+               case QH_STATE_COMPLETING:
+                       unlink_async (ehci, qh);
+                       break;
+               case QH_STATE_UNLINK:
+               case QH_STATE_UNLINK_WAIT:
+                       /* already started */
+                       break;
+               case QH_STATE_IDLE:
+                       WARN_ON(1);
+                       break;
+               }
                break;
 
        case PIPE_INTERRUPT:
@@ -847,6 +867,7 @@ rescan:
                unlink_async (ehci, qh);
                /* FALL THROUGH */
        case QH_STATE_UNLINK:           /* wait for hw to finish? */
+       case QH_STATE_UNLINK_WAIT:
 idle_timeout:
                spin_unlock_irqrestore (&ehci->lock, flags);
                schedule_timeout_uninterruptible(1);
index d03e3cad5ca8a90a2cf7319a2f92891b481a1784..b2ee13c58517cc9182fccc533c7c5ca4aff0c77a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 by David Brownell
- * 
+ *
  * 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
@@ -48,7 +48,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
        }
        ehci->command = readl (&ehci->regs->command);
        if (ehci->reclaim)
-               ehci->reclaim_ready = 1;
+               end_unlink_async (ehci, NULL);
        ehci_work(ehci, NULL);
 
        /* suspend any active/unsuspended ports, maybe allow wakeup */
@@ -103,10 +103,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
 
        /* re-init operational registers in case we lost power */
        if (readl (&ehci->regs->intr_enable) == 0) {
-               /* at least some APM implementations will try to deliver
+               /* at least some APM implementations will try to deliver
                 * IRQs right away, so delay them until we're ready.
-                */
-               intr_enable = 1;
+                */
+               intr_enable = 1;
                writel (0, &ehci->regs->segment);
                writel (ehci->periodic_dma, &ehci->regs->frame_list);
                writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next);
@@ -232,7 +232,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
                buf [1] = 0;
                retval++;
        }
-       
+
        /* no hub change reports (bit 0) for now (power, ...) */
 
        /* port N changes (bit N)? */
@@ -304,7 +304,7 @@ ehci_hub_descriptor (
 
 /*-------------------------------------------------------------------------*/
 
-#define        PORT_WAKE_BITS  (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
+#define        PORT_WAKE_BITS  (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
 
 static int ehci_hub_control (
        struct usb_hcd  *hcd,
index 766061e0260a5e96d6258149bc6f7f8a31f71ee9..a8ba2e1497a4fb6d9f7b46bc6068b0cc6fd56371 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2001 by David Brownell
- * 
+ *
  * 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
@@ -25,7 +25,7 @@
  *     - data used only by the HCD ... kmalloc is fine
  *     - async and periodic schedules, shared by HC and HCD ... these
  *       need to use dma_pool or dma_alloc_coherent
- *     - driver buffers, read/written by HC ... single shot DMA mapped 
+ *     - driver buffers, read/written by HC ... single shot DMA mapped
  *
  * There's also PCI "register" data, which is memory mapped.
  * No memory seen by this driver is pageable.
@@ -119,7 +119,7 @@ static inline void qh_put (struct ehci_qh *qh)
 
 /*-------------------------------------------------------------------------*/
 
-/* The queue heads and transfer descriptors are managed from pools tied 
+/* The queue heads and transfer descriptors are managed from pools tied
  * to each of the "per device" structures.
  * This is the initialisation and cleanup code.
  */
@@ -165,7 +165,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
        int i;
 
        /* QTDs for control/bulk/intr transfers */
-       ehci->qtd_pool = dma_pool_create ("ehci_qtd", 
+       ehci->qtd_pool = dma_pool_create ("ehci_qtd",
                        ehci_to_hcd(ehci)->self.controller,
                        sizeof (struct ehci_qtd),
                        32 /* byte alignment (for hw parts) */,
@@ -175,7 +175,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
        }
 
        /* QHs for control/bulk/intr transfers */
-       ehci->qh_pool = dma_pool_create ("ehci_qh", 
+       ehci->qh_pool = dma_pool_create ("ehci_qh",
                        ehci_to_hcd(ehci)->self.controller,
                        sizeof (struct ehci_qh),
                        32 /* byte alignment (for hw parts) */,
@@ -189,7 +189,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
        }
 
        /* ITD for high speed ISO transfers */
-       ehci->itd_pool = dma_pool_create ("ehci_itd", 
+       ehci->itd_pool = dma_pool_create ("ehci_itd",
                        ehci_to_hcd(ehci)->self.controller,
                        sizeof (struct ehci_itd),
                        32 /* byte alignment (for hw parts) */,
@@ -199,7 +199,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags)
        }
 
        /* SITD for full/low speed split ISO transfers */
-       ehci->sitd_pool = dma_pool_create ("ehci_sitd", 
+       ehci->sitd_pool = dma_pool_create ("ehci_sitd",
                        ehci_to_hcd(ehci)->self.controller,
                        sizeof (struct ehci_sitd),
                        32 /* byte alignment (for hw parts) */,
index cadffacd945b9d392ab93a96663b7233865ed918..08d0472d4f57f4201e430a625f18702fccdfdc10 100644 (file)
@@ -238,6 +238,12 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
        writel (0, &ehci->regs->intr_enable);
        (void)readl(&ehci->regs->intr_enable);
 
+       /* make sure snapshot being resumed re-enumerates everything */
+       if (message.event == PM_EVENT_PRETHAW) {
+               ehci_halt(ehci);
+               ehci_reset(ehci);
+       }
+
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
  bail:
        spin_unlock_irqrestore (&ehci->lock, flags);
@@ -297,7 +303,7 @@ restart:
        /* emptying the schedule aborts any urbs */
        spin_lock_irq(&ehci->lock);
        if (ehci->reclaim)
-               ehci->reclaim_ready = 1;
+               end_unlink_async (ehci, NULL);
        ehci_work(ehci, NULL);
        spin_unlock_irq(&ehci->lock);
 
@@ -332,6 +338,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
        .resume =               ehci_pci_resume,
 #endif
        .stop =                 ehci_stop,
+       .shutdown =             ehci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -378,4 +385,5 @@ static struct pci_driver ehci_pci_driver = {
        .suspend =      usb_hcd_pci_suspend,
        .resume =       usb_hcd_pci_resume,
 #endif
+       .shutdown =     usb_hcd_pci_shutdown,
 };
index e469221e7ec392088fd1274e278175e29644f7a8..7fc25b6bd7d249f487e4d2adf8a4ecc150613733 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001-2004 by David Brownell
- * 
+ *
  * 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
@@ -31,7 +31,7 @@
  * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with
  * interrupts) needs careful scheduling.  Performance improvements can be
  * an ongoing challenge.  That's in "ehci-sched.c".
- * 
+ *
  * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs,
  * or otherwise through transaction translators (TTs) in USB 2.0 hubs using
  * (b) special fields in qh entries or (c) split iso entries.  TTs will
@@ -199,7 +199,7 @@ static void qtd_copy_status (
                                && ((token & QTD_STS_MMF) != 0
                                        || QTD_CERR(token) == 0)
                                && (!ehci_is_TDI(ehci)
-                                       || urb->dev->tt->hub !=
+                                       || urb->dev->tt->hub !=
                                           ehci_to_hcd(ehci)->self.root_hub)) {
 #ifdef DEBUG
                        struct usb_device *tt = urb->dev->tt->hub;
@@ -364,7 +364,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
                         */
                        if (likely (urb->status == -EINPROGRESS))
                                continue;
-                       
+
                        /* issue status after short control reads */
                        if (unlikely (do_status != 0)
                                        && QTD_PID (token) == 0 /* OUT */) {
@@ -388,7 +388,7 @@ halt:
                                wmb ();
                        }
                }
+
                /* remove it from the queue */
                spin_lock (&urb->lock);
                qtd_copy_status (ehci, urb, qtd->length, token);
@@ -518,7 +518,7 @@ qh_urb_transaction (
                /* for zero length DATA stages, STATUS is always IN */
                if (len == 0)
                        token |= (1 /* "in" */ << 8);
-       } 
+       }
 
        /*
         * data transfer stage:  buffer setup
@@ -759,7 +759,7 @@ qh_make (
                }
                break;
        default:
-               dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed);
+               dbg ("bogus dev %p speed %d", urb->dev, urb->dev->speed);
 done:
                qh_put (qh);
                return NULL;
@@ -967,17 +967,16 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
        struct ehci_qh          *qh = ehci->reclaim;
        struct ehci_qh          *next;
 
-       timer_action_done (ehci, TIMER_IAA_WATCHDOG);
+       iaa_watchdog_done (ehci);
 
        // qh->hw_next = cpu_to_le32 (qh->qh_dma);
        qh->qh_state = QH_STATE_IDLE;
        qh->qh_next.qh = NULL;
-       qh_put (qh);                    // refcount from reclaim 
+       qh_put (qh);                    // refcount from reclaim
 
        /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
        next = qh->reclaim;
        ehci->reclaim = next;
-       ehci->reclaim_ready = 0;
        qh->reclaim = NULL;
 
        qh_completions (ehci, qh, regs);
@@ -1031,7 +1030,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
                        timer_action_done (ehci, TIMER_ASYNC_OFF);
                }
                return;
-       } 
+       }
 
        qh->qh_state = QH_STATE_UNLINK;
        ehci->reclaim = qh = qh_get (qh);
@@ -1046,17 +1045,16 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
        if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) {
                /* if (unlikely (qh->reclaim != 0))
-                *      this will recurse, probably not much
+                *      this will recurse, probably not much
                 */
                end_unlink_async (ehci, NULL);
                return;
        }
 
-       ehci->reclaim_ready = 0;
        cmd |= CMD_IAAD;
        writel (cmd, &ehci->regs->command);
        (void) readl (&ehci->regs->command);
-       timer_action (ehci, TIMER_IAA_WATCHDOG);
+       iaa_watchdog_start (ehci);
 }
 
 /*-------------------------------------------------------------------------*/
index 4859900bd1351df16b10746b37977dbc217d03cd..e5e9c653c90725ea99d54e5c40c4d3dd0753f01f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2001-2004 by David Brownell
  * Copyright (c) 2003 Michal Sojka, for high-speed iso transfers
- * 
+ *
  * 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
@@ -613,7 +613,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 /*-------------------------------------------------------------------------*/
 
 static int check_period (
-       struct ehci_hcd *ehci, 
+       struct ehci_hcd *ehci,
        unsigned        frame,
        unsigned        uframe,
        unsigned        period,
@@ -629,7 +629,7 @@ static int check_period (
 
        /*
         * 80% periodic == 100 usec/uframe available
-        * convert "usecs we need" to "max already claimed" 
+        * convert "usecs we need" to "max already claimed"
         */
        usecs = 100 - usecs;
 
@@ -659,14 +659,14 @@ static int check_period (
 }
 
 static int check_intr_schedule (
-       struct ehci_hcd         *ehci, 
+       struct ehci_hcd         *ehci,
        unsigned                frame,
        unsigned                uframe,
        const struct ehci_qh    *qh,
        __le32                  *c_maskp
 )
 {
-       int             retval = -ENOSPC;
+       int             retval = -ENOSPC;
        u8              mask = 0;
 
        if (qh->c_usecs && uframe >= 6)         /* FSTN territory? */
@@ -701,7 +701,7 @@ static int check_intr_schedule (
        /* Make sure this tt's buffer is also available for CSPLITs.
         * We pessimize a bit; probably the typical full speed case
         * doesn't need the second CSPLIT.
-        * 
+        *
         * NOTE:  both SPLIT and CSPLIT could be checked in just
         * one smart pass...
         */
@@ -728,7 +728,7 @@ done:
  */
 static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-       int             status;
+       int             status;
        unsigned        uframe;
        __le32          c_mask;
        unsigned        frame;          /* 0..(qh->period - 1), or NO_FRAME */
@@ -784,7 +784,7 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
                ehci_dbg (ehci, "reused qh %p schedule\n", qh);
 
        /* stuff into the periodic schedule */
-       status = qh_link_periodic (ehci, qh);
+       status = qh_link_periodic (ehci, qh);
 done:
        return status;
 }
@@ -1681,7 +1681,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb,
                status = -ESHUTDOWN;
        else
                status = iso_stream_schedule (ehci, urb, stream);
-       if (likely (status == 0))
+       if (likely (status == 0))
                itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
        spin_unlock_irqrestore (&ehci->lock, flags);
 
@@ -1738,7 +1738,7 @@ sitd_sched_init (
                if (packet->buf1 != (buf & ~(u64)0x0fff))
                        packet->cross = 1;
 
-               /* OUT uses multiple start-splits */ 
+               /* OUT uses multiple start-splits */
                if (stream->bEndpointAddress & USB_DIR_IN)
                        continue;
                length = (length + 187) / 188;
@@ -1925,7 +1925,7 @@ sitd_link_urb (
 /*-------------------------------------------------------------------------*/
 
 #define        SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \
-                               | SITD_STS_XACT | SITD_STS_MMF)
+                               | SITD_STS_XACT | SITD_STS_MMF)
 
 static unsigned
 sitd_complete (
@@ -2043,7 +2043,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb,
                status = -ESHUTDOWN;
        else
                status = iso_stream_schedule (ehci, urb, stream);
-       if (status == 0)
+       if (status == 0)
                sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream);
        spin_unlock_irqrestore (&ehci->lock, flags);
 
@@ -2226,5 +2226,5 @@ restart:
                        now_uframe++;
                        now_uframe %= mod;
                }
-       } 
+       }
 }
index 679c1cdcc9154d286235cbe99c7451cf26751e65..6aac39f50e0734d35e33f2fb3cfd5c6e2fcec627 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2001-2002 by David Brownell
- * 
+ *
  * 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
@@ -58,7 +58,6 @@ struct ehci_hcd {                     /* one per controller */
        /* async schedule support */
        struct ehci_qh          *async;
        struct ehci_qh          *reclaim;
-       unsigned                reclaim_ready : 1;
        unsigned                scanning : 1;
 
        /* periodic schedule support */
@@ -81,8 +80,8 @@ struct ehci_hcd {                     /* one per controller */
        struct dma_pool         *itd_pool;      /* itd per iso urb */
        struct dma_pool         *sitd_pool;     /* sitd per split iso urb */
 
+       struct timer_list       iaa_watchdog;
        struct timer_list       watchdog;
-       struct notifier_block   reboot_notifier;
        unsigned long           actions;
        unsigned                stamp;
        unsigned long           next_statechange;
@@ -104,7 +103,7 @@ struct ehci_hcd {                   /* one per controller */
 #endif
 };
 
-/* convert between an HCD pointer and the corresponding EHCI_HCD */ 
+/* convert between an HCD pointer and the corresponding EHCI_HCD */
 static inline struct ehci_hcd *hcd_to_ehci (struct usb_hcd *hcd)
 {
        return (struct ehci_hcd *) (hcd->hcd_priv);
@@ -115,9 +114,21 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci)
 }
 
 
+static inline void
+iaa_watchdog_start (struct ehci_hcd *ehci)
+{
+       WARN_ON(timer_pending(&ehci->iaa_watchdog));
+       mod_timer (&ehci->iaa_watchdog,
+                       jiffies + msecs_to_jiffies(EHCI_IAA_MSECS));
+}
+
+static inline void iaa_watchdog_done (struct ehci_hcd *ehci)
+{
+       del_timer (&ehci->iaa_watchdog);
+}
+
 enum ehci_timer_action {
        TIMER_IO_WATCHDOG,
-       TIMER_IAA_WATCHDOG,
        TIMER_ASYNC_SHRINK,
        TIMER_ASYNC_OFF,
 };
@@ -135,9 +146,6 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
                unsigned long t;
 
                switch (action) {
-               case TIMER_IAA_WATCHDOG:
-                       t = EHCI_IAA_JIFFIES;
-                       break;
                case TIMER_IO_WATCHDOG:
                        t = EHCI_IO_JIFFIES;
                        break;
@@ -154,8 +162,7 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action)
                // async queue SHRINK often precedes IAA.  while it's ready
                // to go OFF neither can matter, and afterwards the IO
                // watchdog stops unless there's still periodic traffic.
-               if (action != TIMER_IAA_WATCHDOG
-                               && t > ehci->watchdog.expires
+               if (time_before_eq(t, ehci->watchdog.expires)
                                && timer_pending (&ehci->watchdog))
                        return;
                mod_timer (&ehci->watchdog, t);
@@ -179,8 +186,8 @@ struct ehci_caps {
 #define HCS_INDICATOR(p)       ((p)&(1 << 16)) /* true: has port indicators */
 #define HCS_N_CC(p)            (((p)>>12)&0xf) /* bits 15:12, #companion HCs */
 #define HCS_N_PCC(p)           (((p)>>8)&0xf)  /* bits 11:8, ports per CC */
-#define HCS_PORTROUTED(p)      ((p)&(1 << 7))  /* true: port routing */ 
-#define HCS_PPC(p)             ((p)&(1 << 4))  /* true: port power control */ 
+#define HCS_PORTROUTED(p)      ((p)&(1 << 7))  /* true: port routing */
+#define HCS_PPC(p)             ((p)&(1 << 4))  /* true: port power control */
 #define HCS_N_PORTS(p)         (((p)>>0)&0xf)  /* bits 3:0, ports on HC */
 
        u32             hcc_params;      /* HCCPARAMS - offset 0x8 */
@@ -205,7 +212,7 @@ struct ehci_regs {
 #define CMD_LRESET     (1<<7)          /* partial reset (no ports, etc) */
 #define CMD_IAAD       (1<<6)          /* "doorbell" interrupt async advance */
 #define CMD_ASE                (1<<5)          /* async schedule enable */
-#define CMD_PSE        (1<<4)          /* periodic schedule enable */
+#define CMD_PSE                (1<<4)          /* periodic schedule enable */
 /* 3:2 is periodic frame list size */
 #define CMD_RESET      (1<<1)          /* reset HC not bus */
 #define CMD_RUN                (1<<0)          /* start/stop HC */
@@ -231,9 +238,9 @@ struct ehci_regs {
        /* FRINDEX: offset 0x0C */
        u32             frame_index;    /* current microframe number */
        /* CTRLDSSEGMENT: offset 0x10 */
-       u32             segment;        /* address bits 63:32 if needed */
+       u32             segment;        /* address bits 63:32 if needed */
        /* PERIODICLISTBASE: offset 0x14 */
-       u32             frame_list;     /* points to periodic list */
+       u32             frame_list;     /* points to periodic list */
        /* ASYNCLISTADDR: offset 0x18 */
        u32             async_next;     /* address of next async queue head */
 
@@ -302,7 +309,7 @@ struct ehci_dbg_port {
 
 /*
  * EHCI Specification 0.95 Section 3.5
- * QTD: describe data transfer components (buffer, direction, ...) 
+ * QTD: describe data transfer components (buffer, direction, ...)
  * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
  *
  * These are associated only with "QH" (Queue Head) structures,
@@ -312,7 +319,7 @@ struct ehci_qtd {
        /* first part defined by EHCI spec */
        __le32                  hw_next;          /* see EHCI 3.5.1 */
        __le32                  hw_alt_next;      /* see EHCI 3.5.2 */
-       __le32                  hw_token;         /* see EHCI 3.5.3 */       
+       __le32                  hw_token;         /* see EHCI 3.5.3 */
 #define        QTD_TOGGLE      (1 << 31)       /* data toggle */
 #define        QTD_LENGTH(tok) (((tok)>>16) & 0x7fff)
 #define        QTD_IOC         (1 << 15)       /* interrupt on complete */
@@ -349,8 +356,8 @@ struct ehci_qtd {
 /* values for that type tag */
 #define Q_TYPE_ITD     __constant_cpu_to_le32 (0 << 1)
 #define Q_TYPE_QH      __constant_cpu_to_le32 (1 << 1)
-#define Q_TYPE_SITD    __constant_cpu_to_le32 (2 << 1)
-#define Q_TYPE_FSTN    __constant_cpu_to_le32 (3 << 1)
+#define Q_TYPE_SITD    __constant_cpu_to_le32 (2 << 1)
+#define Q_TYPE_FSTN    __constant_cpu_to_le32 (3 << 1)
 
 /* next async queue entry, or pointer to interrupt/periodic QH */
 #define        QH_NEXT(dma)    (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH)
@@ -367,7 +374,7 @@ struct ehci_qtd {
  * For entries in the async schedule, the type tag always says "qh".
  */
 union ehci_shadow {
-       struct ehci_qh          *qh;            /* Q_TYPE_QH */
+       struct ehci_qh          *qh;            /* Q_TYPE_QH */
        struct ehci_itd         *itd;           /* Q_TYPE_ITD */
        struct ehci_sitd        *sitd;          /* Q_TYPE_SITD */
        struct ehci_fstn        *fstn;          /* Q_TYPE_FSTN */
@@ -397,7 +404,7 @@ struct ehci_qh {
 #define        QH_HUBPORT      0x3f800000
 #define        QH_MULT         0xc0000000
        __le32                  hw_current;      /* qtd list - see EHCI 3.6.4 */
-       
+
        /* qtd overlay (hardware parts of a struct ehci_qtd) */
        __le32                  hw_qtd_next;
        __le32                  hw_alt_next;
@@ -472,7 +479,7 @@ struct ehci_iso_stream {
        struct list_head        td_list;        /* queued itds/sitds */
        struct list_head        free_list;      /* list of unused itds/sitds */
        struct usb_device       *udev;
-       struct usb_host_endpoint *ep;
+       struct usb_host_endpoint *ep;
 
        /* output of (re)scheduling */
        unsigned long           start;          /* jiffies */
@@ -492,8 +499,8 @@ struct ehci_iso_stream {
        unsigned                bandwidth;
 
        /* This is used to initialize iTD's hw_bufp fields */
-       __le32                  buf0;           
-       __le32                  buf1;           
+       __le32                  buf0;
+       __le32                  buf1;
        __le32                  buf2;
 
        /* this is used to initialize sITD's tt info */
@@ -521,7 +528,7 @@ struct ehci_itd {
 
 #define ITD_ACTIVE     __constant_cpu_to_le32(EHCI_ISOC_ACTIVE)
 
-       __le32                  hw_bufp [7];    /* see EHCI 3.3.3 */ 
+       __le32                  hw_bufp [7];    /* see EHCI 3.3.3 */
        __le32                  hw_bufp_hi [7]; /* Appendix B */
 
        /* the rest is HCD-private */
@@ -542,7 +549,7 @@ struct ehci_itd {
 /*-------------------------------------------------------------------------*/
 
 /*
- * EHCI Specification 0.95 Section 3.4 
+ * EHCI Specification 0.95 Section 3.4
  * siTD, aka split-transaction isochronous Transfer Descriptor
  *       ... describe full speed iso xfers through TT in hubs
  * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD)
index 5147ed4a66626f5a75a89b6da80f14b90a51b7cc..a72e041df8e7256b800c08226493ea46df82b32b 100644 (file)
@@ -1204,10 +1204,10 @@ static int isp116x_show_dbg(struct seq_file *s, void *unused)
 
 static int isp116x_open_seq(struct inode *inode, struct file *file)
 {
-       return single_open(file, isp116x_show_dbg, inode->u.generic_ip);
+       return single_open(file, isp116x_show_dbg, inode->i_private);
 }
 
-static struct file_operations isp116x_debug_fops = {
+static const struct file_operations isp116x_debug_fops = {
        .open = isp116x_open_seq,
        .read = seq_read,
        .llseek = seq_lseek,
index a1b7c3813d3a955321d08961b0a5fc98faecbff4..b91e2edd9c5c1415ebecfe7aa056cddcb15c4fc6 100644 (file)
@@ -233,7 +233,7 @@ static const int cc_to_error[16] = {
        /* Bit Stuff  */ -EPROTO,
        /* Data Togg  */ -EILSEQ,
        /* Stall      */ -EPIPE,
-       /* DevNotResp */ -ETIMEDOUT,
+       /* DevNotResp */ -ETIME,
        /* PIDCheck   */ -EPROTO,
        /* UnExpPID   */ -EPROTO,
        /* DataOver   */ -EOVERFLOW,
index 85cc059705a645e947eae76f13be929048f8eef4..b466581beb4a777499e4ae1e5934471368cea3bd 100644 (file)
@@ -193,7 +193,7 @@ ohci_at91_start (struct usb_hcd *hcd)
        if ((ret = ohci_init(ohci)) < 0)
                return ret;
 
-       root->maxchild = board->ports;
+       ohci->num_ports = board->ports;
 
        if ((ret = ohci_run(ohci)) < 0) {
                err("can't start %s", hcd->self.bus_name);
@@ -221,6 +221,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
         */
        .start =                ohci_at91_start,
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -239,7 +240,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
-
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -296,6 +297,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev)
        if (!clocked) {
                clk_enable(iclk);
                clk_enable(fclk);
+               clocked = 1;
        }
 
        return 0;
@@ -310,6 +312,7 @@ MODULE_ALIAS("at91_ohci");
 static struct platform_driver ohci_hcd_at91_driver = {
        .probe          = ohci_hcd_at91_drv_probe,
        .remove         = ohci_hcd_at91_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
        .suspend        = ohci_hcd_at91_drv_suspend,
        .resume         = ohci_hcd_at91_drv_resume,
        .driver         = {
index f7a975d5db097757965b758baf14612c86b72f62..24e23c5783d85da4d5f05d01eec90d7752fed83d 100644 (file)
@@ -268,11 +268,8 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
         * basic lifecycle operations
         */
        .start =                ohci_au1xxx_start,
-#ifdef CONFIG_PM
-       /* suspend:             ohci_au1xxx_suspend,  -- tbd */
-       /* resume:              ohci_au1xxx_resume,   -- tbd */
-#endif /*CONFIG_PM*/
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -291,6 +288,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -338,6 +336,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct platform_device *dev)
 static struct platform_driver ohci_hcd_au1xxx_driver = {
        .probe          = ohci_hcd_au1xxx_drv_probe,
        .remove         = ohci_hcd_au1xxx_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
        /*.suspend      = ohci_hcd_au1xxx_drv_suspend, */
        /*.resume       = ohci_hcd_au1xxx_drv_resume, */
        .driver         = {
index 7bfffcbbd226ec5a6089e775a2116825027b5988..8293c1d4be3f3049e0fb531cff33966436803541 100644 (file)
@@ -477,7 +477,7 @@ show_async (struct class_device *class_dev, char *buf)
        unsigned long           flags;
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ohci = hcd_to_ohci(hcd);
 
        /* display control and bulk lists together, for simplicity */
@@ -510,7 +510,7 @@ show_periodic (struct class_device *class_dev, char *buf)
        seen_count = 0;
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ohci = hcd_to_ohci(hcd);
        next = buf;
        size = PAGE_SIZE;
@@ -607,7 +607,7 @@ show_registers (struct class_device *class_dev, char *buf)
        u32                     rdata;
 
        bus = class_get_devdata(class_dev);
-       hcd = bus->hcpriv;
+       hcd = bus_to_hcd(bus);
        ohci = hcd_to_ohci(hcd);
        regs = ohci->regs;
        next = buf;
@@ -667,6 +667,11 @@ show_registers (struct class_device *class_dev, char *buf)
        size -= temp;
        next += temp;
 
+       temp = scnprintf (next, size, "hub poll timer %s\n",
+                       ohci_to_hcd(ohci)->poll_rh ? "ON" : "off");
+       size -= temp;
+       next += temp;
+
        /* roothub */
        ohci_dump_roothub (ohci, 1, &next, &size);
 
@@ -680,10 +685,11 @@ static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 static inline void create_debug_files (struct ohci_hcd *ohci)
 {
        struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev;
+       int retval;
 
-       class_device_create_file(cldev, &class_device_attr_async);
-       class_device_create_file(cldev, &class_device_attr_periodic);
-       class_device_create_file(cldev, &class_device_attr_registers);
+       retval = class_device_create_file(cldev, &class_device_attr_async);
+       retval = class_device_create_file(cldev, &class_device_attr_periodic);
+       retval = class_device_create_file(cldev, &class_device_attr_registers);
        ohci_dbg (ohci, "created debug files\n");
 }
 
index 6531c4d26527208eb6dac426a93d59ef36939546..1bf5e7a4e73551749803a85aed745e0b47898763 100644 (file)
@@ -128,12 +128,14 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
        .flags                  = HCD_USB11 | HCD_MEMORY,
        .start                  = ohci_ep93xx_start,
        .stop                   = ohci_stop,
+       .shutdown               = ohci_shutdown,
        .urb_enqueue            = ohci_urb_enqueue,
        .urb_dequeue            = ohci_urb_dequeue,
        .endpoint_disable       = ohci_endpoint_disable,
        .get_frame_number       = ohci_get_frame,
        .hub_status_data        = ohci_hub_status_data,
        .hub_control            = ohci_hub_control,
+       .hub_irq_enable         = ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend            = ohci_bus_suspend,
        .bus_resume             = ohci_bus_resume,
@@ -202,6 +204,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev)
 static struct platform_driver ohci_hcd_ep93xx_driver = {
        .probe          = ohci_hcd_ep93xx_drv_probe,
        .remove         = ohci_hcd_ep93xx_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
 #ifdef CONFIG_PM
        .suspend        = ohci_hcd_ep93xx_drv_suspend,
        .resume         = ohci_hcd_ep93xx_drv_resume,
index 94d8cf4b36c19cf1472ae3c64d5874d143fd60fa..1027aa04583d28e1a3d373e0499d55a4e5f59cbe 100644 (file)
@@ -88,7 +88,7 @@
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/usb.h>
-#include <linux/usb_otg.h>
+#include <linux/usb/otg.h>
 #include <linux/dma-mapping.h> 
 #include <linux/dmapool.h>
 #include <linux/reboot.h>
 
 #include "../core/hcd.h"
 
-#define DRIVER_VERSION "2005 April 22"
+#define DRIVER_VERSION "2006 August 04"
 #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
 #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"
 
 #undef OHCI_VERBOSE_DEBUG      /* not always helpful */
 
 /* For initializing controller (mask in an HCFS mode too) */
-#define        OHCI_CONTROL_INIT       OHCI_CTRL_CBSR
+#define        OHCI_CONTROL_INIT       OHCI_CTRL_CBSR
 #define        OHCI_INTR_INIT \
-       (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH)
+               (OHCI_INTR_MIE | OHCI_INTR_RHSC | OHCI_INTR_UE \
+               | OHCI_INTR_RD | OHCI_INTR_WDH)
 
 #ifdef __hppa__
 /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
 
 static const char      hcd_name [] = "ohci_hcd";
 
+#define        STATECHANGE_DELAY       msecs_to_jiffies(300)
+
 #include "ohci.h"
 
 static void ohci_dump (struct ohci_hcd *ohci, int verbose);
 static int ohci_init (struct ohci_hcd *ohci);
 static void ohci_stop (struct usb_hcd *hcd);
-static int ohci_reboot (struct notifier_block *, unsigned long , void *);
 
 #include "ohci-hub.c"
 #include "ohci-dbg.c"
@@ -416,21 +418,20 @@ static void ohci_usb_reset (struct ohci_hcd *ohci)
        ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
 }
 
-/* reboot notifier forcibly disables IRQs and DMA, helping kexec and
+/* ohci_shutdown forcibly disables IRQs and DMA, helping kexec and
  * other cases where the next software may expect clean state from the
  * "firmware".  this is bus-neutral, unlike shutdown() methods.
  */
-static int
-ohci_reboot (struct notifier_block *block, unsigned long code, void *null)
+static void
+ohci_shutdown (struct usb_hcd *hcd)
 {
        struct ohci_hcd *ohci;
 
-       ohci = container_of (block, struct ohci_hcd, reboot_notifier);
+       ohci = hcd_to_ohci (hcd);
        ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
        ohci_usb_reset (ohci);
        /* flush the writes */
        (void) ohci_readl (ohci, &ohci->regs->control);
-       return 0;
 }
 
 /*-------------------------------------------------------------------------*
@@ -446,7 +447,6 @@ static int ohci_init (struct ohci_hcd *ohci)
 
        disable (ohci);
        ohci->regs = hcd->regs;
-       ohci->next_statechange = jiffies;
 
        /* REVISIT this BIOS handshake is now moved into PCI "quirks", and
         * was never needed for most non-PCI systems ... remove the code?
@@ -502,7 +502,6 @@ static int ohci_init (struct ohci_hcd *ohci)
        if ((ret = ohci_mem_init (ohci)) < 0)
                ohci_stop (hcd);
        else {
-               register_reboot_notifier (&ohci->reboot_notifier);
                create_debug_files (ohci);
        }
 
@@ -637,10 +636,14 @@ retry:
                return -EOVERFLOW;
        }
 
-       /* start controller operations */
+       /* use rhsc irqs after khubd is fully initialized */
+       hcd->poll_rh = 1;
+       hcd->uses_new_polling = 1;
+
+       /* start controller operations */
        ohci->hc_control &= OHCI_CTRL_RWC;
-       ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
-       ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
+       ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
+       ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
        hcd->state = HC_STATE_RUNNING;
 
        /* wake on ConnectStatusChange, matching external hubs */
@@ -648,7 +651,7 @@ retry:
 
        /* Choose the interrupts we care about now, others later on demand */
        mask = OHCI_INTR_INIT;
-       ohci_writel (ohci, mask, &ohci->regs->intrstatus);
+       ohci_writel (ohci, ~0, &ohci->regs->intrstatus);
        ohci_writel (ohci, mask, &ohci->regs->intrenable);
 
        /* handle root hub init quirks ... */
@@ -672,6 +675,7 @@ retry:
        // flush those writes
        (void) ohci_readl (ohci, &ohci->regs->control);
 
+       ohci->next_statechange = jiffies + STATECHANGE_DELAY;
        spin_unlock_irq (&ohci->lock);
 
        // POTPGT delay is bits 24-31, in 2 ms units.
@@ -709,7 +713,23 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
        /* interrupt for some other device? */
        } else if ((ints &= ohci_readl (ohci, &regs->intrenable)) == 0) {
                return IRQ_NOTMINE;
-       } 
+       }
+
+       /* NOTE:  vendors didn't always make the same implementation
+        * choices for RHSC.  Sometimes it triggers on an edge (like
+        * setting and maybe clearing a port status change bit); and
+        * it's level-triggered on other silicon, active until khubd
+        * clears all active port status change bits.  Poll by timer
+        * til it's fully debounced and the difference won't matter.
+        */
+       if (ints & OHCI_INTR_RHSC) {
+               ohci_vdbg (ohci, "rhsc\n");
+               ohci_writel (ohci, OHCI_INTR_RHSC, &regs->intrdisable);
+               hcd->poll_rh = 1;
+               ohci->next_statechange = jiffies + STATECHANGE_DELAY;
+               ohci_writel (ohci, OHCI_INTR_RHSC, &regs->intrstatus);
+               usb_hcd_poll_rh_status(hcd);
+       }
 
        if (ints & OHCI_INTR_UE) {
                disable (ohci);
@@ -775,9 +795,10 @@ static void ohci_stop (struct usb_hcd *hcd)
 
        ohci_usb_reset (ohci);
        ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-       
+       free_irq(hcd->irq, hcd);
+       hcd->irq = -1;
+
        remove_debug_files (ohci);
-       unregister_reboot_notifier (&ohci->reboot_notifier);
        ohci_mem_cleanup (ohci);
        if (ohci->hcca) {
                dma_free_coherent (hcd->self.controller, 
@@ -917,6 +938,10 @@ MODULE_LICENSE ("GPL");
 #include "ohci-at91.c"
 #endif
 
+#ifdef CONFIG_ARCH_PNX4008
+#include "ohci-pnx4008.c"
+#endif
+
 #if !(defined(CONFIG_PCI) \
       || defined(CONFIG_SA1111) \
       || defined(CONFIG_ARCH_S3C2410) \
@@ -928,6 +953,7 @@ MODULE_LICENSE ("GPL");
       || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
       || defined (CONFIG_ARCH_AT91RM9200) \
       || defined (CONFIG_ARCH_AT91SAM9261) \
+      || defined (CONFIG_ARCH_PNX4008) \
        )
 #error "missing bus glue for ohci-hcd"
 #endif
index 5b0a23fd798bb46294885432878e4c6429a660ed..0b899339cac807e58c98a3377e8b3fbae0bab2f1 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
+/* hcd->hub_irq_enable() */
+static void ohci_rhsc_enable (struct usb_hcd *hcd)
+{
+       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
+
+       ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
+}
+
 #ifdef CONFIG_PM
 
 #define OHCI_SCHED_ENABLES \
@@ -123,10 +131,10 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
        /* no resumes until devices finish suspending */
        ohci->next_statechange = jiffies + msecs_to_jiffies (5);
 
+       /* no timer polling */
+       hcd->poll_rh = 0;
+
 done:
-       /* external suspend vs self autosuspend ... same effect */
-       if (status == 0)
-               usb_hcd_suspend_root_hub(hcd);
        spin_unlock_irqrestore (&ohci->lock, flags);
        return status;
 }
@@ -256,8 +264,8 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
        /* TRSMRCY */
        msleep (10);
 
-       /* keep it alive for ~5x suspend + resume costs */
-       ohci->next_statechange = jiffies + msecs_to_jiffies (250);
+       /* keep it alive for more than ~5x suspend + resume costs */
+       ohci->next_statechange = jiffies + STATECHANGE_DELAY;
 
        /* maybe turn schedules back on */
        enables = 0;
@@ -302,9 +310,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
 {
        struct ohci_hcd *ohci = hcd_to_ohci (hcd);
        int             i, changed = 0, length = 1;
-       int             can_suspend = device_may_wakeup(&hcd->self.root_hub->dev);
+       int             can_suspend;
        unsigned long   flags;
 
+       can_suspend = device_may_wakeup(&hcd->self.root_hub->dev);
        spin_lock_irqsave (&ohci->lock, flags);
 
        /* handle autosuspended root:  finish resuming before
@@ -339,6 +348,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
        for (i = 0; i < ohci->num_ports; i++) {
                u32     status = roothub_portstatus (ohci, i);
 
+               /* can't autosuspend with active ports */
+               if ((status & RH_PS_PES) && !(status & RH_PS_PSS))
+                       can_suspend = 0;
+
                if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
                                | RH_PS_OCIC | RH_PS_PRSC)) {
                        changed = 1;
@@ -348,32 +361,41 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
                            buf [1] |= 1 << (i - 7);
                        continue;
                }
+       }
 
-               /* can suspend if no ports are enabled; or if all all
-                * enabled ports are suspended AND remote wakeup is on.
-                */
-               if (!(status & RH_PS_CCS))
-                       continue;
-               if ((status & RH_PS_PSS) && can_suspend)
-                       continue;
+       /* after root hub changes, stop polling after debouncing
+        * for a while and maybe kicking in autosuspend
+        */
+       if (changed) {
+               ohci->next_statechange = jiffies + STATECHANGE_DELAY;
                can_suspend = 0;
+       } else if (time_before (jiffies, ohci->next_statechange)) {
+               can_suspend = 0;
+       } else {
+#ifdef CONFIG_PM
+               can_suspend = can_suspend
+                       && !ohci->ed_rm_list
+                       && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES)
+                                       & ohci->hc_control)
+                               == OHCI_USB_OPER;
+#endif
+               if (hcd->uses_new_polling) {
+                       hcd->poll_rh = 0;
+                       /* use INTR_RHSC iff INTR_RD won't apply */
+                       if (!can_suspend)
+                               ohci_writel (ohci, OHCI_INTR_RHSC,
+                                               &ohci->regs->intrenable);
+               }
        }
+
 done:
        spin_unlock_irqrestore (&ohci->lock, flags);
 
-#ifdef CONFIG_PM
-       /* save power by suspending idle root hubs;
+#ifdef CONFIG_PM
+       /* save power by autosuspending idle root hubs;
         * INTR_RD wakes us when there's work
         */
-       if (can_suspend
-                       && !changed
-                       && !ohci->ed_rm_list
-                       && ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES)
-                                       & ohci->hc_control)
-                               == OHCI_USB_OPER
-                       && time_after (jiffies, ohci->next_statechange)
-                       && usb_trylock_device (hcd->self.root_hub) == 0
-                       ) {
+       if (can_suspend && usb_trylock_device (hcd->self.root_hub) == 0) {
                ohci_vdbg (ohci, "autosuspend\n");
                (void) ohci_bus_suspend (hcd);
                usb_unlock_device (hcd->self.root_hub);
index 5602da9bd52c9446e6706544f7acb11a57672aea..e121d97ed91caf7e3a7d3c3d9616f9baa5a19093 100644 (file)
@@ -173,11 +173,8 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
         * basic lifecycle operations
         */
        .start =                ohci_lh7a404_start,
-#ifdef CONFIG_PM
-       /* suspend:             ohci_lh7a404_suspend,  -- tbd */
-       /* resume:              ohci_lh7a404_resume,   -- tbd */
-#endif /*CONFIG_PM*/
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -196,6 +193,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -244,6 +242,7 @@ static int ohci_hcd_lh7a404_drv_resume(struct platform_device *dev)
 static struct platform_driver ohci_hcd_lh7a404_driver = {
        .probe          = ohci_hcd_lh7a404_drv_probe,
        .remove         = ohci_hcd_lh7a404_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
        /*.suspend      = ohci_hcd_lh7a404_drv_suspend, */
        /*.resume       = ohci_hcd_lh7a404_drv_resume, */
        .driver         = {
index bfbe328a47885671f833c3e84f6b9c26f4f6854f..d976614eebd3b33055bf8b2dd7f327187c55f43b 100644 (file)
@@ -28,7 +28,6 @@ static void ohci_hcd_init (struct ohci_hcd *ohci)
        ohci->next_statechange = jiffies;
        spin_lock_init (&ohci->lock);
        INIT_LIST_HEAD (&ohci->pending);
-       ohci->reboot_notifier.notifier_call = ohci_reboot;
 }
 
 /*-------------------------------------------------------------------------*/
index c4c4babd4767f52bd12ed0a67586021a471f1b43..9c02177de50a85a15836301d87993c31e5b41438 100644 (file)
@@ -4,7 +4,7 @@
  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
  * (C) Copyright 2000-2005 David Brownell
  * (C) Copyright 2002 Hewlett-Packard Company
- * 
+ *
  * OMAP Bus Glue
  *
  * Modified for OMAP by Tony Lindgren <tony@atomide.com>
@@ -66,15 +66,20 @@ extern int usb_disabled(void);
 extern int ocpi_enable(void);
 
 static struct clk *usb_host_ck;
+static struct clk *usb_dc_ck;
+static int host_enabled;
+static int host_initialized;
 
 static void omap_ohci_clock_power(int on)
 {
        if (on) {
+               clk_enable(usb_dc_ck);
                clk_enable(usb_host_ck);
                /* guesstimate for T5 == 1x 32K clock + APLL lock time */
                udelay(100);
        } else {
                clk_disable(usb_host_ck);
+               clk_disable(usb_dc_ck);
        }
 }
 
@@ -87,14 +92,14 @@ static int omap_ohci_transceiver_power(int on)
        if (on) {
                if (machine_is_omap_innovator() && cpu_is_omap1510())
                        fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
-                               | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), 
+                               | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
                               INNOVATOR_FPGA_CAM_USB_CONTROL);
                else if (machine_is_omap_osk())
                        tps65010_set_gpio_out_value(GPIO1, LOW);
        } else {
                if (machine_is_omap_innovator() && cpu_is_omap1510())
                        fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
-                               & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), 
+                               & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
                               INNOVATOR_FPGA_CAM_USB_CONTROL);
                else if (machine_is_omap_osk())
                        tps65010_set_gpio_out_value(GPIO1, HIGH);
@@ -103,6 +108,7 @@ static int omap_ohci_transceiver_power(int on)
        return 0;
 }
 
+#ifdef CONFIG_ARCH_OMAP15XX
 /*
  * OMAP-1510 specific Local Bus clock on/off
  */
@@ -121,8 +127,8 @@ static int omap_1510_local_bus_power(int on)
 /*
  * OMAP-1510 specific Local Bus initialization
  * NOTE: This assumes 32MB memory size in OMAP1510LB_MEMSIZE.
- *       See also arch/mach-omap/memory.h for __virt_to_dma() and 
- *       __dma_to_virt() which need to match with the physical 
+ *       See also arch/mach-omap/memory.h for __virt_to_dma() and
+ *       __dma_to_virt() which need to match with the physical
  *       Local Bus address below.
  */
 static int omap_1510_local_bus_init(void)
@@ -130,7 +136,7 @@ static int omap_1510_local_bus_init(void)
        unsigned int tlb;
        unsigned long lbaddr, physaddr;
 
-       omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4, 
+       omap_writel((omap_readl(OMAP1510_LB_CLOCK_DIV) & 0xfffffff8) | 0x4,
               OMAP1510_LB_CLOCK_DIV);
 
        /* Configure the Local Bus MMU table */
@@ -138,7 +144,7 @@ static int omap_1510_local_bus_init(void)
                lbaddr = tlb * 0x00100000 + OMAP1510_LB_OFFSET;
                physaddr = tlb * 0x00100000 + PHYS_OFFSET;
                omap_writel((lbaddr & 0x0fffffff) >> 22, OMAP1510_LB_MMU_CAM_H);
-               omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc, 
+               omap_writel(((lbaddr & 0x003ffc00) >> 6) | 0xc,
                       OMAP1510_LB_MMU_CAM_L);
                omap_writel(physaddr >> 16, OMAP1510_LB_MMU_RAM_H);
                omap_writel((physaddr & 0x0000fc00) | 0x300, OMAP1510_LB_MMU_RAM_L);
@@ -152,6 +158,10 @@ static int omap_1510_local_bus_init(void)
 
        return 0;
 }
+#else
+#define omap_1510_local_bus_power(x)   {}
+#define omap_1510_local_bus_init()     {}
+#endif
 
 #ifdef CONFIG_USB_OTG
 
@@ -173,13 +183,14 @@ static void start_hnp(struct ohci_hcd *ohci)
 
 /*-------------------------------------------------------------------------*/
 
-static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
+static int ohci_omap_init(struct usb_hcd *hcd)
 {
-       struct omap_usb_config  *config = pdev->dev.platform_data;
+       struct ohci_hcd         *ohci = hcd_to_ohci(hcd);
+       struct omap_usb_config  *config = hcd->self.controller->platform_data;
        int                     need_transceiver = (config->otg != 0);
        int                     ret;
 
-       dev_dbg(&pdev->dev, "starting USB Controller\n");
+       dev_dbg(hcd->self.controller, "starting USB Controller\n");
 
        if (config->otg) {
                ohci_to_hcd(ohci)->self.otg_port = config->otg;
@@ -200,7 +211,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
                if (ohci->transceiver) {
                        int     status = otg_set_host(ohci->transceiver,
                                                &ohci_to_hcd(ohci)->self);
-                       dev_dbg(&pdev->dev, "init %s transceiver, status %d\n",
+                       dev_dbg(hcd->self.controller, "init %s transceiver, status %d\n",
                                        ohci->transceiver->label, status);
                        if (status) {
                                if (ohci->transceiver)
@@ -208,7 +219,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
                                return status;
                        }
                } else {
-                       dev_err(&pdev->dev, "can't find transceiver\n");
+                       dev_err(hcd->self.controller, "can't find transceiver\n");
                        return -ENODEV;
                }
        }
@@ -247,6 +258,10 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
                }
                ohci_writel(ohci, rh, &ohci->regs->roothub.a);
                distrust_firmware = 0;
+       } else if (machine_is_nokia770()) {
+               /* We require a self-powered hub, which should have
+                * plenty of power. */
+               ohci_to_hcd(ohci)->power_budget = 0;
        }
 
        /* FIXME khubd hub requests should manage power switching */
@@ -260,21 +275,15 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
        return 0;
 }
 
-static void omap_stop_hc(struct platform_device *pdev)
+static void ohci_omap_stop(struct usb_hcd *hcd)
 {
-       dev_dbg(&pdev->dev, "stopping USB Controller\n");
+       dev_dbg(hcd->self.controller, "stopping USB Controller\n");
        omap_ohci_clock_power(0);
 }
 
 
 /*-------------------------------------------------------------------------*/
 
-void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
-
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
-
-
 /**
  * usb_hcd_omap_probe - initialize OMAP-based HCDs
  * Context: !in_interrupt()
@@ -283,7 +292,7 @@ void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
  * then invokes the start() method for the HCD associated with it
  * through the hotplug entry's driver_data.
  */
-int usb_hcd_omap_probe (const struct hc_driver *driver,
+static int usb_hcd_omap_probe (const struct hc_driver *driver,
                          struct platform_device *pdev)
 {
        int retval, irq;
@@ -291,12 +300,12 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
        struct ohci_hcd *ohci;
 
        if (pdev->num_resources != 2) {
-               printk(KERN_ERR "hcd probe: invalid num_resources: %i\n", 
+               printk(KERN_ERR "hcd probe: invalid num_resources: %i\n",
                       pdev->num_resources);
                return -ENODEV;
        }
 
-       if (pdev->resource[0].flags != IORESOURCE_MEM 
+       if (pdev->resource[0].flags != IORESOURCE_MEM
                        || pdev->resource[1].flags != IORESOURCE_IRQ) {
                printk(KERN_ERR "hcd probe: invalid resource type\n");
                return -ENODEV;
@@ -306,6 +315,17 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
        if (IS_ERR(usb_host_ck))
                return PTR_ERR(usb_host_ck);
 
+       if (!cpu_is_omap1510())
+               usb_dc_ck = clk_get(0, "usb_dc_ck");
+       else
+               usb_dc_ck = clk_get(0, "lb_ck");
+
+       if (IS_ERR(usb_dc_ck)) {
+               clk_put(usb_host_ck);
+               return PTR_ERR(usb_dc_ck);
+       }
+
+
        hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
        if (!hcd) {
                retval = -ENOMEM;
@@ -325,9 +345,8 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
        ohci = hcd_to_ohci(hcd);
        ohci_hcd_init(ohci);
 
-       retval = omap_start_hc(ohci, pdev);
-       if (retval < 0)
-               goto err2;
+       host_initialized = 0;
+       host_enabled = 1;
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
@@ -335,15 +354,21 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
                goto err2;
        }
        retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
-       if (retval == 0)
-               return retval;
+       if (retval)
+               goto err2;
+
+       host_initialized = 1;
+
+       if (!host_enabled)
+               omap_ohci_clock_power(0);
 
-       omap_stop_hc(pdev);
+       return 0;
 err2:
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
 err1:
        usb_put_hcd(hcd);
 err0:
+       clk_put(usb_dc_ck);
        clk_put(usb_host_ck);
        return retval;
 }
@@ -359,31 +384,41 @@ err0:
  * Reverses the effect of usb_hcd_omap_probe(), first invoking
  * the HCD's stop() method.  It is always called from a thread
  * context, normally "rmmod", "apmd", or something similar.
- *
  */
-void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
+static inline void
+usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 {
+       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
+
        usb_remove_hcd(hcd);
+       if (ohci->transceiver) {
+               (void) otg_set_host(ohci->transceiver, 0);
+               put_device(ohci->transceiver->dev);
+       }
        if (machine_is_omap_osk())
                omap_free_gpio(9);
-       omap_stop_hc(pdev);
        release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        usb_put_hcd(hcd);
+       clk_put(usb_dc_ck);
        clk_put(usb_host_ck);
 }
 
 /*-------------------------------------------------------------------------*/
 
-static int __devinit
+static int
 ohci_omap_start (struct usb_hcd *hcd)
 {
        struct omap_usb_config *config;
        struct ohci_hcd *ohci = hcd_to_ohci (hcd);
        int             ret;
 
+       if (!host_enabled)
+               return 0;
        config = hcd->self.controller->platform_data;
-       if (config->otg || config->rwc)
+       if (config->otg || config->rwc) {
+               ohci->hc_control = OHCI_CTRL_RWC;
                writel(OHCI_CTRL_RWC, &ohci->regs->control);
+       }
 
        if ((ret = ohci_run (ohci)) < 0) {
                dev_err(hcd->self.controller, "can't start\n");
@@ -409,8 +444,10 @@ static const struct hc_driver ohci_omap_hc_driver = {
        /*
         * basic lifecycle operations
         */
+       .reset =                ohci_omap_init,
        .start =                ohci_omap_start,
-       .stop =                 ohci_stop,
+       .stop =                 ohci_omap_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -429,6 +466,7 @@ static const struct hc_driver ohci_omap_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -446,13 +484,8 @@ static int ohci_hcd_omap_drv_probe(struct platform_device *dev)
 static int ohci_hcd_omap_drv_remove(struct platform_device *dev)
 {
        struct usb_hcd          *hcd = platform_get_drvdata(dev);
-       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
 
        usb_hcd_omap_remove(hcd, dev);
-       if (ohci->transceiver) {
-               (void) otg_set_host(ohci->transceiver, 0);
-               put_device(ohci->transceiver->dev);
-       }
        platform_set_drvdata(dev, NULL);
 
        return 0;
@@ -472,7 +505,7 @@ static int ohci_omap_suspend(struct platform_device *dev, pm_message_t message)
 
        omap_ohci_clock_power(0);
        ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
-       dev->power.power_state = PMSG_SUSPEND;
+       dev->dev.power.power_state = PMSG_SUSPEND;
        return 0;
 }
 
@@ -485,8 +518,8 @@ static int ohci_omap_resume(struct platform_device *dev)
        ohci->next_statechange = jiffies;
 
        omap_ohci_clock_power(1);
-       dev->power.power_state = PMSG_ON;
-       usb_hcd_resume_root_hub(dev_get_drvdata(dev));
+       dev->dev.power.power_state = PMSG_ON;
+       usb_hcd_resume_root_hub(platform_get_drvdata(dev));
        return 0;
 }
 
@@ -500,6 +533,7 @@ static int ohci_omap_resume(struct platform_device *dev)
 static struct platform_driver ohci_hcd_omap_driver = {
        .probe          = ohci_hcd_omap_drv_probe,
        .remove         = ohci_hcd_omap_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
 #ifdef CONFIG_PM
        .suspend        = ohci_omap_suspend,
        .resume         = ohci_omap_resume,
index b268537e389eb04a228bab160b00e0f20dabd60d..3732db7d68eb58ed193130ff47f9aea20fc910e6 100644 (file)
@@ -135,6 +135,11 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
        }
        ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
        (void)ohci_readl(ohci, &ohci->regs->intrdisable);
+
+       /* make sure snapshot being resumed re-enumerates everything */
+       if (message.event == PM_EVENT_PRETHAW)
+               ohci_usb_reset(ohci);
+
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
  bail:
        spin_unlock_irqrestore (&ohci->lock, flags);
@@ -171,11 +176,14 @@ static const struct hc_driver ohci_pci_hc_driver = {
         */
        .reset =                ohci_pci_reset,
        .start =                ohci_pci_start,
+       .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
+
 #ifdef CONFIG_PM
+       /* these suspend/resume entries are for upstream PCI glue ONLY */
        .suspend =              ohci_pci_suspend,
        .resume =               ohci_pci_resume,
 #endif
-       .stop =                 ohci_stop,
 
        /*
         * managing i/o requests and associated device resources
@@ -194,6 +202,7 @@ static const struct hc_driver ohci_pci_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -224,6 +233,8 @@ static struct pci_driver ohci_pci_driver = {
        .suspend =      usb_hcd_pci_suspend,
        .resume =       usb_hcd_pci_resume,
 #endif
+
+       .shutdown =     usb_hcd_pci_shutdown,
 };
 
  
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
new file mode 100644 (file)
index 0000000..82cb22f
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * drivers/usb/host/ohci-pnx4008.c
+ *
+ * driver for Philips PNX4008 USB Host
+ *
+ * Authors: Dmitry Chigirev <source@mvista.com>
+ *         Vitaly Wool <vitalywool@gmail.com>
+ *
+ * register initialization is based on code examples provided by Philips
+ * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
+ *
+ * NOTE: This driver does not have suspend/resume functionality
+ * This driver is intended for engineering development purposes only
+ *
+ * 2005-2006 (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.
+ */
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/platform.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/gpio.h>
+
+#define USB_CTRL       IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64)
+
+/* USB_CTRL bit defines */
+#define USB_SLAVE_HCLK_EN      (1 << 24)
+#define USB_HOST_NEED_CLK_EN   (1 << 21)
+
+#define USB_OTG_CLK_CTRL       IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF4)
+#define USB_OTG_CLK_STAT       IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF8)
+
+/* USB_OTG_CLK_CTRL bit defines */
+#define AHB_M_CLOCK_ON         (1 << 4)
+#define OTG_CLOCK_ON           (1 << 3)
+#define I2C_CLOCK_ON           (1 << 2)
+#define DEV_CLOCK_ON           (1 << 1)
+#define HOST_CLOCK_ON          (1 << 0)
+
+#define USB_OTG_STAT_CONTROL   IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x110)
+
+/* USB_OTG_STAT_CONTROL bit defines */
+#define TRANSPARENT_I2C_EN     (1 << 7)
+#define HOST_EN                        (1 << 0)
+
+/* ISP1301 USB transceiver I2C registers */
+#define        ISP1301_MODE_CONTROL_1          0x04    /* u8 read, set, +1 clear */
+
+#define        MC1_SPEED_REG           (1 << 0)
+#define        MC1_SUSPEND_REG         (1 << 1)
+#define        MC1_DAT_SE0             (1 << 2)
+#define        MC1_TRANSPARENT         (1 << 3)
+#define        MC1_BDIS_ACON_EN        (1 << 4)
+#define        MC1_OE_INT_EN           (1 << 5)
+#define        MC1_UART_EN             (1 << 6)
+#define        MC1_MASK                0x7f
+
+#define        ISP1301_MODE_CONTROL_2          0x12    /* u8 read, set, +1 clear */
+
+#define        MC2_GLOBAL_PWR_DN       (1 << 0)
+#define        MC2_SPD_SUSP_CTRL       (1 << 1)
+#define        MC2_BI_DI               (1 << 2)
+#define        MC2_TRANSP_BDIR0        (1 << 3)
+#define        MC2_TRANSP_BDIR1        (1 << 4)
+#define        MC2_AUDIO_EN            (1 << 5)
+#define        MC2_PSW_EN              (1 << 6)
+#define        MC2_EN2V7               (1 << 7)
+
+#define        ISP1301_OTG_CONTROL_1           0x06    /* u8 read, set, +1 clear */
+#      define  OTG1_DP_PULLUP          (1 << 0)
+#      define  OTG1_DM_PULLUP          (1 << 1)
+#      define  OTG1_DP_PULLDOWN        (1 << 2)
+#      define  OTG1_DM_PULLDOWN        (1 << 3)
+#      define  OTG1_ID_PULLDOWN        (1 << 4)
+#      define  OTG1_VBUS_DRV           (1 << 5)
+#      define  OTG1_VBUS_DISCHRG       (1 << 6)
+#      define  OTG1_VBUS_CHRG          (1 << 7)
+#define        ISP1301_OTG_STATUS              0x10    /* u8 readonly */
+#      define  OTG_B_SESS_END          (1 << 6)
+#      define  OTG_B_SESS_VLD          (1 << 7)
+
+#define ISP1301_I2C_ADDR 0x2C
+
+#define ISP1301_I2C_MODE_CONTROL_1 0x4
+#define ISP1301_I2C_MODE_CONTROL_2 0x12
+#define ISP1301_I2C_OTG_CONTROL_1 0x6
+#define ISP1301_I2C_OTG_CONTROL_2 0x10
+#define ISP1301_I2C_INTERRUPT_SOURCE 0x8
+#define ISP1301_I2C_INTERRUPT_LATCH 0xA
+#define ISP1301_I2C_INTERRUPT_FALLING 0xC
+#define ISP1301_I2C_INTERRUPT_RISING 0xE
+#define ISP1301_I2C_REG_CLEAR_ADDR 1
+
+struct i2c_driver isp1301_driver;
+struct i2c_client *isp1301_i2c_client;
+
+extern int usb_disabled(void);
+extern int ocpi_enable(void);
+
+static struct clk *usb_clk;
+
+static int isp1301_probe(struct i2c_adapter *adap);
+static int isp1301_detach(struct i2c_client *client);
+static int isp1301_command(struct i2c_client *client, unsigned int cmd,
+                          void *arg);
+
+static unsigned short normal_i2c[] =
+    { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END };
+static unsigned short dummy_i2c_addrlist[] = { I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+       .normal_i2c = normal_i2c,
+       .probe = dummy_i2c_addrlist,
+       .ignore = dummy_i2c_addrlist,
+};
+
+struct i2c_driver isp1301_driver = {
+       .id = I2C_DRIVERID_I2CDEV,      /* Fake Id */
+       .class = I2C_CLASS_HWMON,
+       .attach_adapter = isp1301_probe,
+       .detach_client = isp1301_detach,
+       .command = isp1301_command
+};
+
+static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+       struct i2c_client *c;
+
+       c = (struct i2c_client *)kzalloc(sizeof(*c), SLAB_KERNEL);
+
+       if (!c)
+               return -ENOMEM;
+
+       strcpy(c->name, "isp1301");
+       c->flags = 0;
+       c->addr = addr;
+       c->adapter = adap;
+       c->driver = &isp1301_driver;
+
+       isp1301_i2c_client = c;
+
+       return i2c_attach_client(c);
+}
+
+static int isp1301_probe(struct i2c_adapter *adap)
+{
+       return i2c_probe(adap, &addr_data, isp1301_attach);
+}
+
+static int isp1301_detach(struct i2c_client *client)
+{
+       i2c_detach_client(client);
+       kfree(isp1301_i2c_client);
+       return 0;
+}
+
+/* No commands defined */
+static int isp1301_command(struct i2c_client *client, unsigned int cmd,
+                          void *arg)
+{
+       return 0;
+}
+
+static void i2c_write(u8 buf, u8 subaddr)
+{
+       char tmpbuf[2];
+
+       tmpbuf[0] = subaddr;    /*register number */
+       tmpbuf[1] = buf;        /*register data */
+       i2c_master_send(isp1301_i2c_client, &tmpbuf[0], 2);
+}
+
+static void isp1301_configure(void)
+{
+       /* PNX4008 only supports DAT_SE0 USB mode */
+       /* PNX4008 R2A requires setting the MAX603 to output 3.6V */
+       /* Power up externel charge-pump */
+
+       i2c_write(MC1_DAT_SE0 | MC1_SPEED_REG, ISP1301_I2C_MODE_CONTROL_1);
+       i2c_write(~(MC1_DAT_SE0 | MC1_SPEED_REG),
+                 ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
+       i2c_write(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL,
+                 ISP1301_I2C_MODE_CONTROL_2);
+       i2c_write(~(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL),
+                 ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR);
+       i2c_write(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN,
+                 ISP1301_I2C_OTG_CONTROL_1);
+       i2c_write(~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN),
+                 ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
+       i2c_write(0xFF,
+                 ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR);
+       i2c_write(0xFF,
+                 ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR);
+       i2c_write(0xFF,
+                 ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR);
+
+}
+
+static inline void isp1301_vbus_on(void)
+{
+       i2c_write(OTG1_VBUS_DRV, ISP1301_I2C_OTG_CONTROL_1);
+}
+
+static inline void isp1301_vbus_off(void)
+{
+       i2c_write(OTG1_VBUS_DRV,
+                 ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
+}
+
+static void pnx4008_start_hc(void)
+{
+       unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN;
+       __raw_writel(tmp, USB_OTG_STAT_CONTROL);
+       isp1301_vbus_on();
+}
+
+static void pnx4008_stop_hc(void)
+{
+       unsigned long tmp;
+       isp1301_vbus_off();
+       tmp = __raw_readl(USB_OTG_STAT_CONTROL) & ~HOST_EN;
+       __raw_writel(tmp, USB_OTG_STAT_CONTROL);
+}
+
+static int __devinit ohci_pnx4008_start(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       int ret;
+
+       if ((ret = ohci_init(ohci)) < 0)
+               return ret;
+
+       if ((ret = ohci_run(ohci)) < 0) {
+               dev_err(hcd->self.controller, "can't start\n");
+               ohci_stop(hcd);
+               return ret;
+       }
+       return 0;
+}
+
+static const struct hc_driver ohci_pnx4008_hc_driver = {
+       .description = hcd_name,
+       .product_desc =         "pnx4008 OHCI",
+
+       /*
+        * generic hardware linkage
+        */
+       .irq = ohci_irq,
+       .flags = HCD_USB11 | HCD_MEMORY,
+
+       .hcd_priv_size =        sizeof(struct ohci_hcd),
+       /*
+        * basic lifecycle operations
+        */
+       .start = ohci_pnx4008_start,
+       .stop = ohci_stop,
+
+       /*
+        * managing i/o requests and associated device resources
+        */
+       .urb_enqueue = ohci_urb_enqueue,
+       .urb_dequeue = ohci_urb_dequeue,
+       .endpoint_disable = ohci_endpoint_disable,
+
+       /*
+        * scheduling support
+        */
+       .get_frame_number = ohci_get_frame,
+
+       /*
+        * root hub support
+        */
+       .hub_status_data = ohci_hub_status_data,
+       .hub_control = ohci_hub_control,
+
+       .start_port_reset = ohci_start_port_reset,
+};
+
+#define USB_CLOCK_MASK (AHB_M_CLOCK_ON| OTG_CLOCK_ON | HOST_CLOCK_ON | I2C_CLOCK_ON)
+
+static void pnx4008_set_usb_bits(void)
+{
+       start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N);
+       start_int_ack(SE_USB_OTG_ATX_INT_N);
+       start_int_umask(SE_USB_OTG_ATX_INT_N);
+
+       start_int_set_rising_edge(SE_USB_OTG_TIMER_INT);
+       start_int_ack(SE_USB_OTG_TIMER_INT);
+       start_int_umask(SE_USB_OTG_TIMER_INT);
+
+       start_int_set_rising_edge(SE_USB_I2C_INT);
+       start_int_ack(SE_USB_I2C_INT);
+       start_int_umask(SE_USB_I2C_INT);
+
+       start_int_set_rising_edge(SE_USB_INT);
+       start_int_ack(SE_USB_INT);
+       start_int_umask(SE_USB_INT);
+
+       start_int_set_rising_edge(SE_USB_NEED_CLK_INT);
+       start_int_ack(SE_USB_NEED_CLK_INT);
+       start_int_umask(SE_USB_NEED_CLK_INT);
+
+       start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT);
+       start_int_ack(SE_USB_AHB_NEED_CLK_INT);
+       start_int_umask(SE_USB_AHB_NEED_CLK_INT);
+}
+
+static void pnx4008_unset_usb_bits(void)
+{
+       start_int_mask(SE_USB_OTG_ATX_INT_N);
+       start_int_mask(SE_USB_OTG_TIMER_INT);
+       start_int_mask(SE_USB_I2C_INT);
+       start_int_mask(SE_USB_INT);
+       start_int_mask(SE_USB_NEED_CLK_INT);
+       start_int_mask(SE_USB_AHB_NEED_CLK_INT);
+}
+
+static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = 0;
+       struct ohci_hcd *ohci;
+       const struct hc_driver *driver = &ohci_pnx4008_hc_driver;
+
+       int ret = 0, irq;
+
+       dev_dbg(&pdev->dev, "%s: " DRIVER_INFO " (pnx4008)\n", hcd_name);
+       if (usb_disabled()) {
+               err("USB is disabled");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       if (pdev->num_resources != 2
+           || pdev->resource[0].flags != IORESOURCE_MEM
+           || pdev->resource[1].flags != IORESOURCE_IRQ) {
+               err("Invalid resource configuration");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       /* Enable AHB slave USB clock, needed for further USB clock control */
+       __raw_writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL);
+
+       ret = i2c_add_driver(&isp1301_driver);
+       if (ret < 0) {
+               err("failed to connect I2C to ISP1301 USB Transceiver");
+               goto out;
+       }
+
+       isp1301_configure();
+
+       /* Enable USB PLL */
+       usb_clk = clk_get(&pdev->dev, "ck_pll5");
+       if (IS_ERR(usb_clk)) {
+               err("failed to acquire USB PLL");
+               ret = PTR_ERR(usb_clk);
+               goto out1;
+       }
+
+       ret = clk_enable(usb_clk);
+       if (ret < 0) {
+               err("failed to start USB PLL");
+               goto out2;
+       }
+
+       ret = clk_set_rate(usb_clk, 48000);
+       if (ret < 0) {
+               err("failed to set USB clock rate");
+               goto out3;
+       }
+
+       __raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL);
+
+       /* Set to enable all needed USB clocks */
+       __raw_writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL);
+
+       while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) !=
+              USB_CLOCK_MASK) ;
+
+       hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
+       if (!hcd) {
+               err("Failed to allocate HC buffer");
+               ret = -ENOMEM;
+               goto out3;
+       }
+
+       /* Set all USB bits in the Start Enable register */
+       pnx4008_set_usb_bits();
+
+       hcd->rsrc_start = pdev->resource[0].start;
+       hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
+       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+               dev_dbg(&pdev->dev, "request_mem_region failed\n");
+               ret =  -ENOMEM;
+               goto out4;
+       }
+       hcd->regs = (void __iomem *)pdev->resource[0].start;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               ret = -ENXIO;
+               goto out4;
+       }
+
+       hcd->self.hcpriv = (void *)hcd;
+
+       pnx4008_start_hc();
+       platform_set_drvdata(pdev, hcd);
+       ohci = hcd_to_ohci(hcd);
+       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);
+       if (ret == 0)
+               return ret;
+
+       pnx4008_stop_hc();
+out4:
+       pnx4008_unset_usb_bits();
+       usb_put_hcd(hcd);
+out3:
+       clk_disable(usb_clk);
+out2:
+       clk_put(usb_clk);
+out1:
+       i2c_del_driver(&isp1301_driver);
+out:
+       return ret;
+}
+
+static int usb_hcd_pnx4008_remove(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+       usb_remove_hcd(hcd);
+       pnx4008_stop_hc();
+       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+       usb_put_hcd(hcd);
+       pnx4008_unset_usb_bits();
+       clk_disable(usb_clk);
+       clk_put(usb_clk);
+       i2c_del_driver(&isp1301_driver);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver usb_hcd_pnx4008_driver = {
+       .driver = {
+               .name = "usb-ohci",
+       },
+       .probe = usb_hcd_pnx4008_probe,
+       .remove = usb_hcd_pnx4008_remove,
+};
+
+static int __init usb_hcd_pnx4008_init(void)
+{
+       return platform_driver_register(&usb_hcd_pnx4008_driver);
+}
+
+static void __exit usb_hcd_pnx4008_cleanup(void)
+{
+       return platform_driver_unregister(&usb_hcd_pnx4008_driver);
+}
+
+module_init(usb_hcd_pnx4008_init);
+module_exit(usb_hcd_pnx4008_cleanup);
index 9fe56ff1615dab3740cf6d75b4149c1b3556c131..d9d1ae236bd517458ca7bbd27a80f17663c837c8 100644 (file)
@@ -148,6 +148,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
         */
        .start =                ohci_ppc_soc_start,
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -166,6 +167,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -195,6 +197,7 @@ static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
 static struct platform_driver ohci_hcd_ppc_soc_driver = {
        .probe          = ohci_hcd_ppc_soc_drv_probe,
        .remove         = ohci_hcd_ppc_soc_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
 #ifdef CONFIG_PM
        /*.suspend      = ohci_hcd_ppc_soc_drv_suspend,*/
        /*.resume       = ohci_hcd_ppc_soc_drv_resume,*/
index 6f559e102789462e9efbff65ee30bcbf45e92bf4..e176b04d7aeb4ea4921c102ab614dc69ea037906 100644 (file)
@@ -270,6 +270,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
         */
        .start =                ohci_pxa27x_start,
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -288,6 +289,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef  CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -357,6 +359,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct platform_device *pdev)
 static struct platform_driver ohci_hcd_pxa27x_driver = {
        .probe          = ohci_hcd_pxa27x_drv_probe,
        .remove         = ohci_hcd_pxa27x_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
 #ifdef CONFIG_PM
        .suspend        = ohci_hcd_pxa27x_drv_suspend, 
        .resume         = ohci_hcd_pxa27x_drv_resume,
index d2fc6969a9f77ae6784fe2838aee33e9fe5f9bbe..59e436424d4145fc1e181b3b25c9a047e6b17180 100644 (file)
@@ -370,7 +370,7 @@ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
                goto err_mem;
        }
 
-       usb_clk = clk_get(&dev->dev, "upll");
+       usb_clk = clk_get(&dev->dev, "usb-bus-host");
        if (IS_ERR(usb_clk)) {
                dev_err(&dev->dev, "cannot get usb-host clock\n");
                retval = -ENOENT;
@@ -447,6 +447,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
         */
        .start =                ohci_s3c2410_start,
        .stop =                 ohci_stop,
+       .shutdown =             ohci_shutdown,
 
        /*
         * managing i/o requests and associated device resources
@@ -465,6 +466,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
         */
        .hub_status_data =      ohci_s3c2410_hub_status_data,
        .hub_control =          ohci_s3c2410_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
@@ -490,6 +492,7 @@ static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
 static struct platform_driver ohci_hcd_s3c2410_driver = {
        .probe          = ohci_hcd_s3c2410_drv_probe,
        .remove         = ohci_hcd_s3c2410_drv_remove,
+       .shutdown       = usb_hcd_platform_shutdown,
        /*.suspend      = ohci_hcd_s3c2410_drv_suspend, */
        /*.resume       = ohci_hcd_s3c2410_drv_resume, */
        .driver         = {
index ce3de106cadc46872f8d57491b634c7a2aa2ac67..71371de32ada4c21bed7e61d7a30914ea35db9b4 100644 (file)
@@ -212,10 +212,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
         * basic lifecycle operations
         */
        .start =                ohci_sa1111_start,
-#ifdef CONFIG_PM
-       /* suspend:             ohci_sa1111_suspend,  -- tbd */
-       /* resume:              ohci_sa1111_resume,   -- tbd */
-#endif
        .stop =                 ohci_stop,
 
        /*
@@ -235,6 +231,7 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
         */
        .hub_status_data =      ohci_hub_status_data,
        .hub_control =          ohci_hub_control,
+       .hub_irq_enable =       ohci_rhsc_enable,
 #ifdef CONFIG_PM
        .bus_suspend =          ohci_bus_suspend,
        .bus_resume =           ohci_bus_resume,
index caacf14371f510dd45f031eb0c765d1b6e6aec8c..93fdc3c353416dd46269532156130f2645547a85 100644 (file)
@@ -159,7 +159,7 @@ static const int cc_to_error [16] = {
        /* Bit Stuff  */               -EPROTO,
        /* Data Togg  */               -EILSEQ,
        /* Stall      */               -EPIPE,
-       /* DevNotResp */               -ETIMEDOUT,
+       /* DevNotResp */               -ETIME,
        /* PIDCheck   */               -EPROTO,
        /* UnExpPID   */               -EPROTO,
        /* DataOver   */               -EOVERFLOW,
@@ -389,8 +389,6 @@ struct ohci_hcd {
        unsigned long           next_statechange;       /* suspend/resume */
        u32                     fminterval;             /* saved register */
 
-       struct notifier_block   reboot_notifier;
-
        unsigned long           flags;          /* for HC bugs */
 #define        OHCI_QUIRK_AMD756       0x01                    /* erratum #4 */
 #define        OHCI_QUIRK_SUPERIO      0x02                    /* natsemi */
index fa34092bbcde1e82ac9338d7a2366aea48c2e1d3..3a586aab39395580ef2fa68c3b0e393bd9adbc3b 100644 (file)
@@ -597,7 +597,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs)
        /* error? retry, until "3 strikes" */
        } else if (++ep->error_count >= 3) {
                if (status & SL11H_STATMASK_TMOUT)
-                       urbstat = -ETIMEDOUT;
+                       urbstat = -ETIME;
                else if (status & SL11H_STATMASK_OVF)
                        urbstat = -EOVERFLOW;
                else
@@ -1517,7 +1517,7 @@ static int proc_sl811h_open(struct inode *inode, struct file *file)
        return single_open(file, proc_sl811h_show, PDE(inode)->data);
 }
 
-static struct file_operations proc_ops = {
+static const struct file_operations proc_ops = {
        .open           = proc_sl811h_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
@@ -1783,10 +1783,15 @@ sl811h_suspend(struct platform_device *dev, pm_message_t state)
        struct sl811    *sl811 = hcd_to_sl811(hcd);
        int             retval = 0;
 
-       if (state.event == PM_EVENT_FREEZE)
+       switch (state.event) {
+       case PM_EVENT_FREEZE:
                retval = sl811h_bus_suspend(hcd);
-       else if (state.event == PM_EVENT_SUSPEND)
+               break;
+       case PM_EVENT_SUSPEND:
+       case PM_EVENT_PRETHAW:          /* explicitly discard hw state */
                port_power(sl811, 0);
+               break;
+       }
        if (retval == 0)
                dev->dev.power.power_state = state;
        return retval;
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
new file mode 100644 (file)
index 0000000..cb2e2a6
--- /dev/null
@@ -0,0 +1,3295 @@
+/*
+* Host Controller Driver for the Elan Digital Systems U132 adapter
+*
+* Copyright(C) 2006 Elan Digital Systems Limited
+* http://www.elandigitalsystems.com
+*
+* Author and Maintainer - Tony Olech - Elan Digital Systems
+* tony.olech@elandigitalsystems.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.
+*
+*
+* This driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
+* based on various USB host drivers in the 2.6.15 linux kernel
+* with constant reference to the 3rd Edition of Linux Device Drivers
+* published by O'Reilly
+*
+* The U132 adapter is a USB to CardBus adapter specifically designed
+* for PC cards that contain an OHCI host controller. Typical PC cards
+* are the Orange Mobile 3G Option GlobeTrotter Fusion card.
+*
+* The U132 adapter will *NOT *work with PC cards that do not contain
+* an OHCI controller. A simple way to test whether a PC card has an
+* OHCI controller as an interface is to insert the PC card directly
+* into a laptop(or desktop) with a CardBus slot and if "lspci" shows
+* a new USB controller and "lsusb -v" shows a new OHCI Host Controller
+* then there is a good chance that the U132 adapter will support the
+* PC card.(you also need the specific client driver for the PC card)
+*
+* Please inform the Author and Maintainer about any PC cards that
+* contain OHCI Host Controller and work when directly connected to
+* an embedded CardBus slot but do not work when they are connected
+* via an ELAN U132 adapter.
+*
+*/
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.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>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/pci_ids.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include "../core/hcd.h"
+#include "ohci.h"
+#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
+#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
+        OHCI_INTR_WDH)
+MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited");
+MODULE_DESCRIPTION("U132 USB Host Controller Driver");
+MODULE_LICENSE("GPL");
+#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
+INT_MODULE_PARM(testing, 0);
+/* Some boards misreport power switching/overcurrent*/
+static int distrust_firmware = 1;
+module_param(distrust_firmware, bool, 0);
+MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
+        "t setup");
+DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
+/*
+* u132_module_lock exists to protect access to global variables
+*
+*/
+static struct semaphore u132_module_lock;
+static int u132_exiting = 0;
+static int u132_instances = 0;
+static struct list_head u132_static_list;
+/*
+* end of the global variables protected by u132_module_lock
+*/
+static struct workqueue_struct *workqueue;
+#define MAX_U132_PORTS 7
+#define MAX_U132_ADDRS 128
+#define MAX_U132_UDEVS 4
+#define MAX_U132_ENDPS 100
+#define MAX_U132_RINGS 4
+static const char *cc_to_text[16] = {
+        "No Error ",
+        "CRC Error ",
+        "Bit Stuff ",
+        "Data Togg ",
+        "Stall ",
+        "DevNotResp ",
+        "PIDCheck ",
+        "UnExpPID ",
+        "DataOver ",
+        "DataUnder ",
+        "(for hw) ",
+        "(for hw) ",
+        "BufferOver ",
+        "BuffUnder ",
+        "(for HCD) ",
+        "(for HCD) "
+};
+struct u132_port {
+        struct u132 *u132;
+        int reset;
+        int enable;
+        int power;
+        int Status;
+};
+struct u132_addr {
+        u8 address;
+};
+struct u132_udev {
+        struct kref kref;
+        struct usb_device *usb_device;
+        u8 enumeration;
+        u8 udev_number;
+        u8 usb_addr;
+        u8 portnumber;
+        u8 endp_number_in[16];
+        u8 endp_number_out[16];
+};
+#define ENDP_QUEUE_SHIFT 3
+#define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT)
+#define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1)
+struct u132_urbq {
+        struct list_head urb_more;
+        struct urb *urb;
+};
+struct u132_spin {
+        spinlock_t slock;
+};
+struct u132_endp {
+        struct kref kref;
+        u8 udev_number;
+        u8 endp_number;
+        u8 usb_addr;
+        u8 usb_endp;
+        struct u132 *u132;
+        struct list_head endp_ring;
+        struct u132_ring *ring;
+        unsigned toggle_bits:2;
+        unsigned active:1;
+        unsigned delayed:1;
+        unsigned input:1;
+        unsigned output:1;
+        unsigned pipetype:2;
+        unsigned dequeueing:1;
+        unsigned edset_flush:1;
+        unsigned spare_bits:14;
+        unsigned long jiffies;
+        struct usb_host_endpoint *hep;
+        struct u132_spin queue_lock;
+        u16 queue_size;
+        u16 queue_last;
+        u16 queue_next;
+        struct urb *urb_list[ENDP_QUEUE_SIZE];
+        struct list_head urb_more;
+        struct work_struct scheduler;
+};
+struct u132_ring {
+        unsigned in_use:1;
+        unsigned length:7;
+        u8 number;
+        struct u132 *u132;
+        struct u132_endp *curr_endp;
+        struct work_struct scheduler;
+};
+#define OHCI_QUIRK_AMD756 0x01
+#define OHCI_QUIRK_SUPERIO 0x02
+#define OHCI_QUIRK_INITRESET 0x04
+#define OHCI_BIG_ENDIAN 0x08
+#define OHCI_QUIRK_ZFMICRO 0x10
+struct u132 {
+        struct kref kref;
+        struct list_head u132_list;
+        struct semaphore sw_lock;
+        struct semaphore scheduler_lock;
+        struct u132_platform_data *board;
+        struct platform_device *platform_dev;
+        struct u132_ring ring[MAX_U132_RINGS];
+        int sequence_num;
+        int going;
+        int power;
+        int reset;
+        int num_ports;
+        u32 hc_control;
+        u32 hc_fminterval;
+        u32 hc_roothub_status;
+        u32 hc_roothub_a;
+        u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
+        int flags;
+        unsigned long next_statechange;
+        struct work_struct monitor;
+        int num_endpoints;
+        struct u132_addr addr[MAX_U132_ADDRS];
+        struct u132_udev udev[MAX_U132_UDEVS];
+        struct u132_port port[MAX_U132_PORTS];
+        struct u132_endp *endp[MAX_U132_ENDPS];
+};
+int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data);
+int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs,
+        u8 width, u32 *data);
+int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs,
+        u8 width, u32 data);
+/*
+* these can not be inlines because we need the structure offset!!
+* Does anyone have a better way?????
+*/
+#define u132_read_pcimem(u132, member, data) \
+        usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
+        ohci_regs, member), 0, data);
+#define u132_write_pcimem(u132, member, data) \
+        usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
+        ohci_regs, member), 0, data);
+#define u132_write_pcimem_byte(u132, member, data) \
+        usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
+        ohci_regs, member), 0x0e, data);
+static inline struct u132 *udev_to_u132(struct u132_udev *udev)
+{
+        u8 udev_number = udev->udev_number;
+        return container_of(udev, struct u132, udev[udev_number]);
+}
+
+static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd)
+{
+        return (struct u132 *)(hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *u132_to_hcd(struct u132 *u132)
+{
+        return container_of((void *)u132, struct usb_hcd, hcd_priv);
+}
+
+static inline void u132_disable(struct u132 *u132)
+{
+        u132_to_hcd(u132)->state = HC_STATE_HALT;
+}
+
+
+#define kref_to_u132(d) container_of(d, struct u132, kref)
+#define kref_to_u132_endp(d) container_of(d, struct u132_endp, kref)
+#define kref_to_u132_udev(d) container_of(d, struct u132_udev, kref)
+#include "../misc/usb_u132.h"
+static const char hcd_name[] = "u132_hcd";
+#define PORT_C_MASK ((USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | \
+        USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \
+        USB_PORT_STAT_C_RESET) << 16)
+static void u132_hcd_delete(struct kref *kref)
+{
+        struct u132 *u132 = kref_to_u132(kref);
+        struct platform_device *pdev = u132->platform_dev;
+        struct usb_hcd *hcd = u132_to_hcd(u132);
+        u132->going += 1;
+        down(&u132_module_lock);
+        list_del_init(&u132->u132_list);
+        u132_instances -= 1;
+        up(&u132_module_lock);
+        dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
+                "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
+        usb_put_hcd(hcd);
+}
+
+static inline void u132_u132_put_kref(struct u132 *u132)
+{
+        kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static inline void u132_u132_init_kref(struct u132 *u132)
+{
+        kref_init(&u132->kref);
+}
+
+static void u132_udev_delete(struct kref *kref)
+{
+        struct u132_udev *udev = kref_to_u132_udev(kref);
+        udev->udev_number = 0;
+        udev->usb_device = NULL;
+        udev->usb_addr = 0;
+        udev->enumeration = 0;
+}
+
+static inline void u132_udev_put_kref(struct u132 *u132, struct u132_udev *udev)
+{
+        kref_put(&udev->kref, u132_udev_delete);
+}
+
+static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev)
+{
+        kref_get(&udev->kref);
+}
+
+static inline void u132_udev_init_kref(struct u132 *u132,
+        struct u132_udev *udev)
+{
+        kref_init(&udev->kref);
+}
+
+static inline void u132_ring_put_kref(struct u132 *u132, struct u132_ring *ring)
+{
+        kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring,
+        unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &ring->scheduler, delta))
+                        return;
+        } else if (queue_work(workqueue, &ring->scheduler))
+                return;
+        kref_put(&u132->kref, u132_hcd_delete);
+        return;
+}
+
+static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring,
+        unsigned int delta)
+{
+        kref_get(&u132->kref);
+        u132_ring_requeue_work(u132, ring, delta);
+        return;
+}
+
+static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring)
+{
+        if (cancel_delayed_work(&ring->scheduler)) {
+                kref_put(&u132->kref, u132_hcd_delete);
+        }
+}
+
+static void u132_endp_delete(struct kref *kref)
+{
+        struct u132_endp *endp = kref_to_u132_endp(kref);
+        struct u132 *u132 = endp->u132;
+        u8 usb_addr = endp->usb_addr;
+        u8 usb_endp = endp->usb_endp;
+        u8 address = u132->addr[usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        u8 endp_number = endp->endp_number;
+        struct usb_host_endpoint *hep = endp->hep;
+        struct u132_ring *ring = endp->ring;
+        struct list_head *head = &endp->endp_ring;
+        ring->length -= 1;
+        if (endp == ring->curr_endp) {
+                if (list_empty(head)) {
+                        ring->curr_endp = NULL;
+                        list_del(head);
+                } else {
+                        struct u132_endp *next_endp = list_entry(head->next,
+                                struct u132_endp, endp_ring);
+                        ring->curr_endp = next_endp;
+                        list_del(head);
+        }} else
+                list_del(head);
+        if (endp->input) {
+                udev->endp_number_in[usb_endp] = 0;
+                u132_udev_put_kref(u132, udev);
+        }
+        if (endp->output) {
+                udev->endp_number_out[usb_endp] = 0;
+                u132_udev_put_kref(u132, udev);
+        }
+        u132->endp[endp_number - 1] = NULL;
+        hep->hcpriv = NULL;
+        kfree(endp);
+        u132_u132_put_kref(u132);
+}
+
+static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp)
+{
+        kref_put(&endp->kref, u132_endp_delete);
+}
+
+static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp)
+{
+        kref_get(&endp->kref);
+}
+
+static inline void u132_endp_init_kref(struct u132 *u132,
+        struct u132_endp *endp)
+{
+        kref_init(&endp->kref);
+        kref_get(&u132->kref);
+}
+
+static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
+        unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &endp->scheduler, delta))
+                        kref_get(&endp->kref);
+        } else if (queue_work(workqueue, &endp->scheduler))
+                kref_get(&endp->kref);
+        return;
+}
+
+static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp)
+{
+        if (cancel_delayed_work(&endp->scheduler))
+                kref_put(&endp->kref, u132_endp_delete);
+}
+
+static inline void u132_monitor_put_kref(struct u132 *u132)
+{
+        kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &u132->monitor, delta)) {
+                        kref_get(&u132->kref);
+                }
+        } else if (queue_work(workqueue, &u132->monitor))
+                kref_get(&u132->kref);
+        return;
+}
+
+static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(workqueue, &u132->monitor, delta))
+                        return;
+        } else if (queue_work(workqueue, &u132->monitor))
+                return;
+        kref_put(&u132->kref, u132_hcd_delete);
+        return;
+}
+
+static void u132_monitor_cancel_work(struct u132 *u132)
+{
+        if (cancel_delayed_work(&u132->monitor))
+                kref_put(&u132->kref, u132_hcd_delete);
+}
+
+static int read_roothub_info(struct u132 *u132)
+{
+        u32 revision;
+        int retval;
+        retval = u132_read_pcimem(u132, revision, &revision);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+                        "ntrol\n", retval);
+                return retval;
+        } else if ((revision & 0xFF) == 0x10) {
+        } else if ((revision & 0xFF) == 0x11) {
+        } else {
+                dev_err(&u132->platform_dev->dev, "device revision is not valid"
+                        " %08X\n", revision);
+                return -ENODEV;
+        }
+        retval = u132_read_pcimem(u132, control, &u132->hc_control);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device co"
+                        "ntrol\n", retval);
+                return retval;
+        }
+        retval = u132_read_pcimem(u132, roothub.status,
+                &u132->hc_roothub_status);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+                        "g roothub.status\n", retval);
+                return retval;
+        }
+        retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);
+        if (retval) {
+                dev_err(&u132->platform_dev->dev, "error %d accessing device re"
+                        "g roothub.a\n", retval);
+                return retval;
+        }
+        {
+                int I = u132->num_ports;
+                int i = 0;
+                while (I-- > 0) {
+                        retval = u132_read_pcimem(u132, roothub.portstatus[i],
+                                &u132->hc_roothub_portstatus[i]);
+                        if (retval) {
+                                dev_err(&u132->platform_dev->dev, "error %d acc"
+                                        "essing device roothub.portstatus[%d]\n"
+                                        , retval, i);
+                                return retval;
+                        } else
+                                i += 1;
+                }
+        }
+        return 0;
+}
+
+static void u132_hcd_monitor_work(void *data)
+{
+        struct u132 *u132 = data;
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                u132_monitor_put_kref(u132);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                u132_monitor_put_kref(u132);
+                return;
+        } else {
+                int retval;
+                down(&u132->sw_lock);
+                retval = read_roothub_info(u132);
+                if (retval) {
+                        struct usb_hcd *hcd = u132_to_hcd(u132);
+                        u132_disable(u132);
+                        u132->going = 1;
+                        up(&u132->sw_lock);
+                        usb_hc_died(hcd);
+                        ftdi_elan_gone_away(u132->platform_dev);
+                        u132_monitor_put_kref(u132);
+                        return;
+                } else {
+                        u132_monitor_requeue_work(u132, 500);
+                        up(&u132->sw_lock);
+                        return;
+                }
+        }
+}
+
+static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb, int status)
+{
+        struct u132_ring *ring;
+        unsigned long irqs;
+        struct usb_hcd *hcd = u132_to_hcd(u132);
+        urb->error_count = 0;
+        urb->status = status;
+        urb->hcpriv = NULL;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->queue_next += 1;
+        if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        } else {
+                struct list_head *next = endp->urb_more.next;
+                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+                        urb_more);
+                list_del(next);
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                        urbq->urb;
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                kfree(urbq);
+        } down(&u132->scheduler_lock);
+        ring = endp->ring;
+        ring->in_use = 0;
+        u132_ring_cancel_work(u132, ring);
+        u132_ring_queue_work(u132, ring, 0);
+        up(&u132->scheduler_lock);
+        u132_endp_put_kref(u132, endp);
+        usb_hcd_giveback_urb(hcd, urb, NULL);
+        return;
+}
+
+static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb, int status)
+{
+        u132_endp_put_kref(u132, endp);
+}
+
+static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb, int status)
+{
+        unsigned long irqs;
+        struct usb_hcd *hcd = u132_to_hcd(u132);
+        urb->error_count = 0;
+        urb->status = status;
+        urb->hcpriv = NULL;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->queue_next += 1;
+        if (ENDP_QUEUE_SIZE > --endp->queue_size) {
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        } else {
+                struct list_head *next = endp->urb_more.next;
+                struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
+                        urb_more);
+                list_del(next);
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                        urbq->urb;
+                endp->active = 0;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                kfree(urbq);
+        } usb_hcd_giveback_urb(hcd, urb, NULL);
+        return;
+}
+
+static inline int edset_input(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
+                 urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+static inline int edset_setup(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
+                 urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+static inline int edset_single(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
+                endp, urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
+        struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
+                endp, urb, address, endp->usb_endp, toggle_bits, callback);
+}
+
+
+/*
+* must not LOCK sw_lock
+*
+*/
+static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer + urb->actual_length;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length += len;
+                if ((condition_code == TD_CC_NOERROR) &&
+                        (urb->transfer_buffer_length > urb->actual_length)) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        if (urb->actual_length > 0) {
+                                int retval;
+                                up(&u132->scheduler_lock);
+                                retval = edset_single(u132, ring, endp, urb,
+                                        address, endp->toggle_bits,
+                                        u132_hcd_interrupt_recv);
+                                if (retval == 0) {
+                                } else
+                                        u132_hcd_giveback_urb(u132, endp, urb,
+                                                retval);
+                        } else {
+                                ring->in_use = 0;
+                                endp->active = 0;
+                                endp->jiffies = jiffies +
+                                        msecs_to_jiffies(urb->interval);
+                                u132_ring_cancel_work(u132, ring);
+                                u132_ring_queue_work(u132, ring, 0);
+                                up(&u132->scheduler_lock);
+                                u132_endp_put_kref(u132, endp);
+                        }
+                        return;
+                } else if ((condition_code == TD_DATAUNDERRUN) &&
+                        ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                } else {
+                        if (condition_code == TD_CC_NOERROR) {
+                                endp->toggle_bits = toggle_bits;
+                                usb_settoggle(udev->usb_device, endp->usb_endp,
+                                        0, 1 & toggle_bits);
+                        } else if (condition_code == TD_CC_STALL) {
+                                endp->toggle_bits = 0x2;
+                                usb_settoggle(udev->usb_device, endp->usb_endp,
+                                        0, 0);
+                        } else {
+                                endp->toggle_bits = 0x2;
+                                usb_settoggle(udev->usb_device, endp->usb_endp,
+                                        0, 0);
+                                dev_err(&u132->platform_dev->dev, "urb=%p givin"
+                                        "g back INTERRUPT %s\n", urb,
+                                        cc_to_text[condition_code]);
+                        }
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                urb->actual_length += len;
+                endp->toggle_bits = toggle_bits;
+                if (urb->transfer_buffer_length > urb->actual_length) {
+                        int retval;
+                        up(&u132->scheduler_lock);
+                        retval = edset_output(u132, ring, endp, urb, address,
+                                endp->toggle_bits, u132_hcd_bulk_output_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else {
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer + urb->actual_length;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length += len;
+                if ((condition_code == TD_CC_NOERROR) &&
+                        (urb->transfer_buffer_length > urb->actual_length)) {
+                        int retval;
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, endp->toggle_bits,
+                                u132_hcd_bulk_input_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else if (condition_code == TD_CC_NOERROR) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                } else if ((condition_code == TD_DATAUNDERRUN) &&
+                        ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                } else if (condition_code == TD_DATAUNDERRUN) {
+                        endp->toggle_bits = toggle_bits;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0,
+                                1 & toggle_bits);
+                        dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
+                                ") giving back BULK IN %s\n", urb,
+                                cc_to_text[condition_code]);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb, 0);
+                        return;
+                } else if (condition_code == TD_CC_STALL) {
+                        endp->toggle_bits = 0x2;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                } else {
+                        endp->toggle_bits = 0x2;
+                        usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
+                        dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
+                                "ULK IN code=%d %s\n", urb, condition_code,
+                                cc_to_text[condition_code]);
+                        up(&u132->scheduler_lock);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length = len;
+                if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
+                        TD_DATAUNDERRUN) && ((urb->transfer_flags &
+                        URB_SHORT_NOT_OK) == 0))) {
+                        int retval;
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, 0x3,
+                                u132_hcd_configure_empty_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else if (condition_code == TD_CC_STALL) {
+                        up(&u132->scheduler_lock);
+                        dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
+                                "NPUT STALL urb %p\n", urb);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                } else {
+                        up(&u132->scheduler_lock);
+                        dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
+                                "PUT %s urb %p\n", cc_to_text[condition_code],
+                                urb);
+                        u132_hcd_giveback_urb(u132, endp, urb,
+                                cc_to_error[condition_code]);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                if (usb_pipein(urb->pipe)) {
+                        int retval;
+                        struct u132_ring *ring = endp->ring;
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, 0,
+                                u132_hcd_configure_input_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else {
+                        int retval;
+                        struct u132_ring *ring = endp->ring;
+                        up(&u132->scheduler_lock);
+                        retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                                ring->number, endp, urb, address,
+                                endp->usb_endp, 0,
+                                u132_hcd_configure_empty_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                }
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
+        u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        struct u132_udev *udev = &u132->udev[address];
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                u132->addr[0].address = 0;
+                endp->usb_addr = udev->usb_addr;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
+        u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                int retval;
+                struct u132_ring *ring = endp->ring;
+                up(&u132->scheduler_lock);
+                retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                        ring->number, endp, urb, 0, endp->usb_endp, 0,
+                        u132_hcd_enumeration_empty_recv);
+                if (retval == 0) {
+                } else
+                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, 0);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                int retval;
+                struct u132_ring *ring = endp->ring;
+                u8 *u = urb->transfer_buffer;
+                u8 *b = buf;
+                int L = len;
+                while (L-- > 0) {
+                        *u++ = *b++;
+                }
+                urb->actual_length = len;
+                up(&u132->scheduler_lock);
+                retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
+                        ring->number, endp, urb, address, endp->usb_endp, 0x3,
+                        u132_hcd_initial_empty_sent);
+                if (retval == 0) {
+                } else
+                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
+        int len, int toggle_bits, int error_count, int condition_code,
+        int repeat_number, int halted, int skipped, int actual, int non_null)
+{
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        u8 address = u132->addr[endp->usb_addr].address;
+        down(&u132->scheduler_lock);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                up(&u132->scheduler_lock);
+                u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (endp->dequeueing) {
+                endp->dequeueing = 0;
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
+                return;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
+                return;
+        } else if (urb->status == -EINPROGRESS) {
+                int retval;
+                struct u132_ring *ring = endp->ring;
+                up(&u132->scheduler_lock);
+                retval = usb_ftdi_elan_edset_input(u132->platform_dev,
+                        ring->number, endp, urb, address, endp->usb_endp, 0,
+                        u132_hcd_initial_input_recv);
+                if (retval == 0) {
+                } else
+                        u132_hcd_giveback_urb(u132, endp, urb, retval);
+                return;
+        } else {
+                dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
+                        "s=%d\n", urb, urb->status);
+                up(&u132->scheduler_lock);
+                u132_hcd_giveback_urb(u132, endp, urb, urb->status);
+                return;
+        }
+}
+
+static void u132_hcd_ring_work_scheduler(void *data);
+static void u132_hcd_endp_work_scheduler(void *data);
+/*
+* this work function is only executed from the work queue
+*
+*/
+static void u132_hcd_ring_work_scheduler(void *data)
+{
+        struct u132_ring *ring = data;
+        struct u132 *u132 = ring->u132;
+        down(&u132->scheduler_lock);
+        if (ring->in_use) {
+                up(&u132->scheduler_lock);
+                u132_ring_put_kref(u132, ring);
+                return;
+        } else if (ring->curr_endp) {
+                struct u132_endp *last_endp = ring->curr_endp;
+                struct list_head *scan;
+                struct list_head *head = &last_endp->endp_ring;
+                unsigned long wakeup = 0;
+                list_for_each(scan, head) {
+                        struct u132_endp *endp = list_entry(scan,
+                                struct u132_endp, endp_ring);
+                        if (endp->queue_next == endp->queue_last) {
+                        } else if ((endp->delayed == 0)
+                                || time_after_eq(jiffies, endp->jiffies)) {
+                                ring->curr_endp = endp;
+                                u132_endp_cancel_work(u132, last_endp);
+                                u132_endp_queue_work(u132, last_endp, 0);
+                                up(&u132->scheduler_lock);
+                                u132_ring_put_kref(u132, ring);
+                                return;
+                        } else {
+                                unsigned long delta = endp->jiffies - jiffies;
+                                if (delta > wakeup)
+                                        wakeup = delta;
+                        }
+                }
+                if (last_endp->queue_next == last_endp->queue_last) {
+                } else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
+                        last_endp->jiffies)) {
+                        u132_endp_cancel_work(u132, last_endp);
+                        u132_endp_queue_work(u132, last_endp, 0);
+                        up(&u132->scheduler_lock);
+                        u132_ring_put_kref(u132, ring);
+                        return;
+                } else {
+                        unsigned long delta = last_endp->jiffies - jiffies;
+                        if (delta > wakeup)
+                                wakeup = delta;
+                }
+                if (wakeup > 0) {
+                        u132_ring_requeue_work(u132, ring, wakeup);
+                        up(&u132->scheduler_lock);
+                        return;
+                } else {
+                        up(&u132->scheduler_lock);
+                        u132_ring_put_kref(u132, ring);
+                        return;
+                }
+        } else {
+                up(&u132->scheduler_lock);
+                u132_ring_put_kref(u132, ring);
+                return;
+        }
+}
+
+static void u132_hcd_endp_work_scheduler(void *data)
+{
+        struct u132_ring *ring;
+        struct u132_endp *endp = data;
+        struct u132 *u132 = endp->u132;
+        down(&u132->scheduler_lock);
+        ring = endp->ring;
+        if (endp->edset_flush) {
+                endp->edset_flush = 0;
+                if (endp->dequeueing)
+                        usb_ftdi_elan_edset_flush(u132->platform_dev,
+                                ring->number, endp);
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (endp->active) {
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (ring->in_use) {
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (endp->queue_next == endp->queue_last) {
+                up(&u132->scheduler_lock);
+                u132_endp_put_kref(u132, endp);
+                return;
+        } else if (endp->pipetype == PIPE_INTERRUPT) {
+                u8 address = u132->addr[endp->usb_addr].address;
+                if (ring->in_use) {
+                        up(&u132->scheduler_lock);
+                        u132_endp_put_kref(u132, endp);
+                        return;
+                } else {
+                        int retval;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_single(u132, ring, endp, urb, address,
+                                endp->toggle_bits, u132_hcd_interrupt_recv);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                }
+        } else if (endp->pipetype == PIPE_CONTROL) {
+                u8 address = u132->addr[endp->usb_addr].address;
+                if (ring->in_use) {
+                        up(&u132->scheduler_lock);
+                        u132_endp_put_kref(u132, endp);
+                        return;
+                } else if (address == 0) {
+                        int retval;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_setup(u132, ring, endp, urb, address,
+                                0x2, u132_hcd_initial_setup_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else if (endp->usb_addr == 0) {
+                        int retval;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
+                                u132_hcd_enumeration_address_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                } else {
+                        int retval;
+                        u8 address = u132->addr[endp->usb_addr].address;
+                        struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
+                                endp->queue_next];
+                        endp->active = 1;
+                        ring->curr_endp = endp;
+                        ring->in_use = 1;
+                        up(&u132->scheduler_lock);
+                        retval = edset_setup(u132, ring, endp, urb, address,
+                                0x2, u132_hcd_configure_setup_sent);
+                        if (retval == 0) {
+                        } else
+                                u132_hcd_giveback_urb(u132, endp, urb, retval);
+                        return;
+                }
+        } else {
+                if (endp->input) {
+                        u8 address = u132->addr[endp->usb_addr].address;
+                        if (ring->in_use) {
+                                up(&u132->scheduler_lock);
+                                u132_endp_put_kref(u132, endp);
+                                return;
+                        } else {
+                                int retval;
+                                struct urb *urb = endp->urb_list[
+                                        ENDP_QUEUE_MASK & endp->queue_next];
+                                endp->active = 1;
+                                ring->curr_endp = endp;
+                                ring->in_use = 1;
+                                up(&u132->scheduler_lock);
+                                retval = edset_input(u132, ring, endp, urb,
+                                        address, endp->toggle_bits,
+                                        u132_hcd_bulk_input_recv);
+                                if (retval == 0) {
+                                } else
+                                        u132_hcd_giveback_urb(u132, endp, urb,
+                                                retval);
+                                return;
+                        }
+                } else {        /* output pipe */
+                        u8 address = u132->addr[endp->usb_addr].address;
+                        if (ring->in_use) {
+                                up(&u132->scheduler_lock);
+                                u132_endp_put_kref(u132, endp);
+                                return;
+                        } else {
+                                int retval;
+                                struct urb *urb = endp->urb_list[
+                                        ENDP_QUEUE_MASK & endp->queue_next];
+                                endp->active = 1;
+                                ring->curr_endp = endp;
+                                ring->in_use = 1;
+                                up(&u132->scheduler_lock);
+                                retval = edset_output(u132, ring, endp, urb,
+                                        address, endp->toggle_bits,
+                                        u132_hcd_bulk_output_sent);
+                                if (retval == 0) {
+                                } else
+                                        u132_hcd_giveback_urb(u132, endp, urb,
+                                                retval);
+                                return;
+                        }
+                }
+        }
+}
+
+static void port_power(struct u132 *u132, int pn, int is_on)
+{
+        u132->port[pn].power = is_on;
+}
+
+static void u132_power(struct u132 *u132, int is_on)
+{
+        struct usb_hcd *hcd = u132_to_hcd(u132)
+                ;        /* hub is inactive unless the port is powered */
+        if (is_on) {
+                if (u132->power)
+                        return;
+                u132->power = 1;
+                hcd->self.controller->power.power_state = PMSG_ON;
+        } else {
+                u132->power = 0;
+                hcd->state = HC_STATE_HALT;
+                hcd->self.controller->power.power_state = PMSG_SUSPEND;
+        }
+}
+
+static int u132_periodic_reinit(struct u132 *u132)
+{
+        int retval;
+        u32 fi = u132->hc_fminterval & 0x03fff;
+        u32 fit;
+        u32 fminterval;
+        retval = u132_read_pcimem(u132, fminterval, &fminterval);
+        if (retval)
+                return retval;
+        fit = fminterval & FIT;
+        retval = u132_write_pcimem(u132, fminterval,
+                (fit ^ FIT) | u132->hc_fminterval);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, periodicstart,
+                ((9 *fi) / 10) & 0x3fff);
+        if (retval)
+                return retval;
+        return 0;
+}
+
+static char *hcfs2string(int state)
+{
+        switch (state) {
+        case OHCI_USB_RESET:
+                return "reset";
+        case OHCI_USB_RESUME:
+                return "resume";
+        case OHCI_USB_OPER:
+                return "operational";
+        case OHCI_USB_SUSPEND:
+                return "suspend";
+        }
+        return "?";
+}
+
+static int u132_usb_reset(struct u132 *u132)
+{
+        int retval;
+        retval = u132_read_pcimem(u132, control, &u132->hc_control);
+        if (retval)
+                return retval;
+        u132->hc_control &= OHCI_CTRL_RWC;
+        retval = u132_write_pcimem(u132, control, u132->hc_control);
+        if (retval)
+                return retval;
+        return 0;
+}
+
+static int u132_init(struct u132 *u132)
+{
+        int retval;
+        u32 control;
+        u132_disable(u132);
+        u132->next_statechange =
+                jiffies; /* SMM owns the HC? not for long! */  {
+                u32 control;
+                retval = u132_read_pcimem(u132, control, &control);
+                if (retval)
+                        return retval;
+                if (control & OHCI_CTRL_IR) {
+                        u32 temp = 50;
+                        retval = u132_write_pcimem(u132, intrenable,
+                                OHCI_INTR_OC);
+                        if (retval)
+                                return retval;
+                        retval = u132_write_pcimem_byte(u132, cmdstatus,
+                                OHCI_OCR);
+                        if (retval)
+                                return retval;
+                      check:{
+                                retval = u132_read_pcimem(u132, control,
+                                        &control);
+                                if (retval)
+                                        return retval;
+                        }
+                        if (control & OHCI_CTRL_IR) {
+                                msleep(10);
+                                if (--temp == 0) {
+                                        dev_err(&u132->platform_dev->dev, "USB "
+                                                "HC takeover failed!(BIOS/SMM b"
+                                                "ug) control=%08X\n", control);
+                                        return -EBUSY;
+                                }
+                                goto check;
+                        }
+                        u132_usb_reset(u132);
+                }
+        }
+        retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        if (u132->num_ports == 0) {
+                u32 rh_a = -1;
+                retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+                if (retval)
+                        return retval;
+                u132->num_ports = rh_a & RH_A_NDP;
+                retval = read_roothub_info(u132);
+                if (retval)
+                        return retval;
+        }
+        if (u132->num_ports > MAX_U132_PORTS) {
+                return -EINVAL;
+        }
+        return 0;
+}
+
+
+/* Start an OHCI controller, set the BUS operational
+* resets USB and controller
+* enable interrupts
+*/
+static int u132_run(struct u132 *u132)
+{
+        int retval;
+        u32 control;
+        u32 status;
+        u32 fminterval;
+        u32 periodicstart;
+        u32 cmdstatus;
+        u32 roothub_a;
+        int mask = OHCI_INTR_INIT;
+        int first = u132->hc_fminterval == 0;
+        int sleep_time = 0;
+        int reset_timeout = 30;        /* ... allow extra time */
+        u132_disable(u132);
+        if (first) {
+                u32 temp;
+                retval = u132_read_pcimem(u132, fminterval, &temp);
+                if (retval)
+                        return retval;
+                u132->hc_fminterval = temp & 0x3fff;
+                if (u132->hc_fminterval != FI) {
+                }
+                u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
+        }
+        retval = u132_read_pcimem(u132, control, &u132->hc_control);
+        if (retval)
+                return retval;
+        dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
+                "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
+                u132->hc_control);
+        switch (u132->hc_control & OHCI_CTRL_HCFS) {
+        case OHCI_USB_OPER:
+                sleep_time = 0;
+                break;
+        case OHCI_USB_SUSPEND:
+        case OHCI_USB_RESUME:
+                u132->hc_control &= OHCI_CTRL_RWC;
+                u132->hc_control |= OHCI_USB_RESUME;
+                sleep_time = 10;
+                break;
+        default:
+                u132->hc_control &= OHCI_CTRL_RWC;
+                u132->hc_control |= OHCI_USB_RESET;
+                sleep_time = 50;
+                break;
+        }
+        retval = u132_write_pcimem(u132, control, u132->hc_control);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        msleep(sleep_time);
+        retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+        if (retval)
+                return retval;
+        if (!(roothub_a & RH_A_NPS)) {
+                int temp;        /* power down each port */
+                for (temp = 0; temp < u132->num_ports; temp++) {
+                        retval = u132_write_pcimem(u132,
+                                roothub.portstatus[temp], RH_PS_LSDA);
+                        if (retval)
+                                return retval;
+                }
+        }
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+      retry:retval = u132_read_pcimem(u132, cmdstatus, &status);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_HCR);
+        if (retval)
+                return retval;
+      extra:{
+                retval = u132_read_pcimem(u132, cmdstatus, &status);
+                if (retval)
+                        return retval;
+                if (0 != (status & OHCI_HCR)) {
+                        if (--reset_timeout == 0) {
+                                dev_err(&u132->platform_dev->dev, "USB HC reset"
+                                        " timed out!\n");
+                                return -ENODEV;
+                        } else {
+                                msleep(5);
+                                goto extra;
+                        }
+                }
+        }
+        if (u132->flags & OHCI_QUIRK_INITRESET) {
+                retval = u132_write_pcimem(u132, control, u132->hc_control);
+                if (retval)
+                        return retval;
+                retval = u132_read_pcimem(u132, control, &control);
+                if (retval)
+                        return retval;
+        }
+        retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, hcca, 0x00000000);
+        if (retval)
+                return retval;
+        retval = u132_periodic_reinit(u132);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, fminterval, &fminterval);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
+        if (retval)
+                return retval;
+        if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
+                if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
+                        u132->flags |= OHCI_QUIRK_INITRESET;
+                        goto retry;
+                } else
+                        dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
+                                "\n", fminterval, periodicstart);
+        }                        /* start controller operations */
+        u132->hc_control &= OHCI_CTRL_RWC;
+        u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
+        retval = u132_write_pcimem(u132, control, u132->hc_control);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem_byte(u132, cmdstatus, OHCI_BLF);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+        retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, intrstatus, mask);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, intrdisable,
+                OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
+                OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
+                OHCI_INTR_SO);
+        if (retval)
+                return retval;        /* handle root hub init quirks ... */
+        retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
+        if (retval)
+                return retval;
+        roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
+        if (u132->flags & OHCI_QUIRK_SUPERIO) {
+                roothub_a |= RH_A_NOCP;
+                roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
+                retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+                if (retval)
+                        return retval;
+        } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
+                roothub_a |= RH_A_NPS;
+                retval = u132_write_pcimem(u132, roothub.a, roothub_a);
+                if (retval)
+                        return retval;
+        }
+        retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
+        if (retval)
+                return retval;
+        retval = u132_write_pcimem(u132, roothub.b,
+                (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
+        if (retval)
+                return retval;
+        retval = u132_read_pcimem(u132, control, &control);
+        if (retval)
+                return retval;
+        mdelay((roothub_a >> 23) & 0x1fe);
+        u132_to_hcd(u132)->state = HC_STATE_RUNNING;
+        return 0;
+}
+
+static void u132_hcd_stop(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+                        "ed\n", hcd);
+        } else {
+                down(&u132->sw_lock);
+                msleep(100);
+                u132_power(u132, 0);
+                up(&u132->sw_lock);
+        }
+}
+
+static int u132_hcd_start(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else if (hcd->self.controller) {
+                int retval;
+                struct platform_device *pdev =
+                        to_platform_device(hcd->self.controller);
+                u16 vendor = ((struct u132_platform_data *)
+                        (pdev->dev.platform_data))->vendor;
+                u16 device = ((struct u132_platform_data *)
+                        (pdev->dev.platform_data))->device;
+                down(&u132->sw_lock);
+                msleep(10);
+                if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
+                        u132->flags = OHCI_QUIRK_AMD756;
+                } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
+                        dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
+                                "ounds unavailable\n");
+                } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
+                        u132->flags |= OHCI_QUIRK_ZFMICRO;
+                retval = u132_run(u132);
+                if (retval) {
+                        u132_disable(u132);
+                        u132->going = 1;
+                }
+                msleep(100);
+                up(&u132->sw_lock);
+                return retval;
+        } else {
+                dev_err(&u132->platform_dev->dev, "platform_device missing\n");
+                return -ENODEV;
+        }
+}
+
+static int u132_hcd_reset(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval;
+                down(&u132->sw_lock);
+                retval = u132_init(u132);
+                if (retval) {
+                        u132_disable(u132);
+                        u132->going = 1;
+                }
+                up(&u132->sw_lock);
+                return retval;
+        }
+}
+
+static int create_endpoint_and_queue_int(struct u132 *u132,
+        struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+        gfp_t mem_flags)
+{
+        struct u132_ring *ring;
+        unsigned long irqs;
+        u8 endp_number = ++u132->num_endpoints;
+        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+                kmalloc(sizeof(struct u132_endp), mem_flags);
+        if (!endp) {
+                return -ENOMEM;
+        }
+        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        spin_lock_init(&endp->queue_lock.slock);
+        INIT_LIST_HEAD(&endp->urb_more);
+        ring = endp->ring = &u132->ring[0];
+        if (ring->curr_endp) {
+                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+        } else {
+                INIT_LIST_HEAD(&endp->endp_ring);
+                ring->curr_endp = endp;
+        }
+        ring->length += 1;
+        endp->dequeueing = 0;
+        endp->edset_flush = 0;
+        endp->active = 0;
+        endp->delayed = 0;
+        endp->endp_number = endp_number;
+        endp->u132 = u132;
+        endp->hep = hep;
+        endp->pipetype = usb_pipetype(urb->pipe);
+        u132_endp_init_kref(u132, endp);
+        if (usb_pipein(urb->pipe)) {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+                endp->input = 1;
+                endp->output = 0;
+                udev->endp_number_in[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        } else {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+                endp->input = 0;
+                endp->output = 1;
+                udev->endp_number_out[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        }
+        urb->hcpriv = u132;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->delayed = 1;
+        endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+        endp->udev_number = address;
+        endp->usb_addr = usb_addr;
+        endp->usb_endp = usb_endp;
+        endp->queue_size = 1;
+        endp->queue_last = 0;
+        endp->queue_next = 0;
+        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
+        return 0;
+}
+
+static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+        struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+        u8 usb_endp, u8 address)
+{
+        urb->hcpriv = u132;
+        endp->delayed = 1;
+        endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
+        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        } else {
+                struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+                        GFP_ATOMIC);
+                if (urbq == NULL) {
+                        endp->queue_size -= 1;
+                        return -ENOMEM;
+                } else {
+                        list_add_tail(&urbq->urb_more, &endp->urb_more);
+                        urbq->urb = urb;
+                }
+        }
+        return 0;
+}
+
+static int create_endpoint_and_queue_bulk(struct u132 *u132,
+        struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
+        gfp_t mem_flags)
+{
+        int ring_number;
+        struct u132_ring *ring;
+        unsigned long irqs;
+        u8 endp_number = ++u132->num_endpoints;
+        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+                kmalloc(sizeof(struct u132_endp), mem_flags);
+        if (!endp) {
+                return -ENOMEM;
+        }
+        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        spin_lock_init(&endp->queue_lock.slock);
+        INIT_LIST_HEAD(&endp->urb_more);
+        endp->dequeueing = 0;
+        endp->edset_flush = 0;
+        endp->active = 0;
+        endp->delayed = 0;
+        endp->endp_number = endp_number;
+        endp->u132 = u132;
+        endp->hep = hep;
+        endp->pipetype = usb_pipetype(urb->pipe);
+        u132_endp_init_kref(u132, endp);
+        if (usb_pipein(urb->pipe)) {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 0, 0);
+                ring_number = 3;
+                endp->input = 1;
+                endp->output = 0;
+                udev->endp_number_in[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        } else {
+                endp->toggle_bits = 0x2;
+                usb_settoggle(udev->usb_device, usb_endp, 1, 0);
+                ring_number = 2;
+                endp->input = 0;
+                endp->output = 1;
+                udev->endp_number_out[usb_endp] = endp_number;
+                u132_udev_get_kref(u132, udev);
+        }
+        ring = endp->ring = &u132->ring[ring_number - 1];
+        if (ring->curr_endp) {
+                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+        } else {
+                INIT_LIST_HEAD(&endp->endp_ring);
+                ring->curr_endp = endp;
+        }
+        ring->length += 1;
+        urb->hcpriv = u132;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        endp->udev_number = address;
+        endp->usb_addr = usb_addr;
+        endp->usb_endp = usb_endp;
+        endp->queue_size = 1;
+        endp->queue_last = 0;
+        endp->queue_next = 0;
+        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+        u132_endp_queue_work(u132, endp, 0);
+        return 0;
+}
+
+static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
+         struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+        u8 usb_endp, u8 address)
+{
+        urb->hcpriv = u132;
+        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+        } else {
+                struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
+                        GFP_ATOMIC);
+                if (urbq == NULL) {
+                        endp->queue_size -= 1;
+                        return -ENOMEM;
+                } else {
+                        list_add_tail(&urbq->urb_more, &endp->urb_more);
+                        urbq->urb = urb;
+                }
+        }
+        return 0;
+}
+
+static int create_endpoint_and_queue_control(struct u132 *u132,
+        struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
+        gfp_t mem_flags)
+{
+        struct u132_ring *ring;
+        u8 endp_number = ++u132->num_endpoints;
+        struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
+                kmalloc(sizeof(struct u132_endp), mem_flags);
+        if (!endp) {
+                return -ENOMEM;
+        }
+        INIT_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler, (void *)endp);
+        spin_lock_init(&endp->queue_lock.slock);
+        INIT_LIST_HEAD(&endp->urb_more);
+        ring = endp->ring = &u132->ring[0];
+        if (ring->curr_endp) {
+                list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
+        } else {
+                INIT_LIST_HEAD(&endp->endp_ring);
+                ring->curr_endp = endp;
+        }
+        ring->length += 1;
+        endp->dequeueing = 0;
+        endp->edset_flush = 0;
+        endp->active = 0;
+        endp->delayed = 0;
+        endp->endp_number = endp_number;
+        endp->u132 = u132;
+        endp->hep = hep;
+        u132_endp_init_kref(u132, endp);
+        u132_endp_get_kref(u132, endp);
+        if (usb_addr == 0) {
+                unsigned long irqs;
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                endp->udev_number = address;
+                endp->usb_addr = usb_addr;
+                endp->usb_endp = usb_endp;
+                endp->input = 1;
+                endp->output = 1;
+                endp->pipetype = usb_pipetype(urb->pipe);
+                u132_udev_init_kref(u132, udev);
+                u132_udev_get_kref(u132, udev);
+                udev->endp_number_in[usb_endp] = endp_number;
+                udev->endp_number_out[usb_endp] = endp_number;
+                urb->hcpriv = u132;
+                spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+                endp->queue_size = 1;
+                endp->queue_last = 0;
+                endp->queue_next = 0;
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                u132_endp_queue_work(u132, endp, 0);
+                return 0;
+        } else {                /*(usb_addr > 0) */
+                unsigned long irqs;
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                endp->udev_number = address;
+                endp->usb_addr = usb_addr;
+                endp->usb_endp = usb_endp;
+                endp->input = 1;
+                endp->output = 1;
+                endp->pipetype = usb_pipetype(urb->pipe);
+                u132_udev_get_kref(u132, udev);
+                udev->enumeration = 2;
+                udev->endp_number_in[usb_endp] = endp_number;
+                udev->endp_number_out[usb_endp] = endp_number;
+                urb->hcpriv = u132;
+                spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+                endp->queue_size = 1;
+                endp->queue_last = 0;
+                endp->queue_next = 0;
+                endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                u132_endp_queue_work(u132, endp, 0);
+                return 0;
+        }
+}
+
+static int queue_control_on_old_endpoint(struct u132 *u132,
+        struct usb_host_endpoint *hep, struct urb *urb,
+        struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
+        u8 usb_endp)
+{
+        if (usb_addr == 0) {
+                if (usb_pipein(urb->pipe)) {
+                        urb->hcpriv = u132;
+                        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                                endp->urb_list[ENDP_QUEUE_MASK &
+                                        endp->queue_last++] = urb;
+                        } else {
+                                struct u132_urbq *urbq =
+                                        kmalloc(sizeof(struct u132_urbq),
+                                        GFP_ATOMIC);
+                                if (urbq == NULL) {
+                                        endp->queue_size -= 1;
+                                        return -ENOMEM;
+                                } else {
+                                        list_add_tail(&urbq->urb_more,
+                                                &endp->urb_more);
+                                        urbq->urb = urb;
+                                }
+                        }
+                        return 0;
+                } else {        /* usb_pipeout(urb->pipe) */
+                        struct u132_addr *addr = &u132->addr[usb_dev->devnum];
+                        int I = MAX_U132_UDEVS;
+                        int i = 0;
+                        while (--I > 0) {
+                                struct u132_udev *udev = &u132->udev[++i];
+                                if (udev->usb_device) {
+                                        continue;
+                                } else {
+                                        udev->enumeration = 1;
+                                        u132->addr[0].address = i;
+                                        endp->udev_number = i;
+                                        udev->udev_number = i;
+                                        udev->usb_addr = usb_dev->devnum;
+                                        u132_udev_init_kref(u132, udev);
+                                        udev->endp_number_in[usb_endp] =
+                                                endp->endp_number;
+                                        u132_udev_get_kref(u132, udev);
+                                        udev->endp_number_out[usb_endp] =
+                                                endp->endp_number;
+                                        udev->usb_device = usb_dev;
+                                        ((u8 *) (urb->setup_packet))[2] =
+                                                addr->address = i;
+                                        u132_udev_get_kref(u132, udev);
+                                        break;
+                                }
+                        }
+                        if (I == 0) {
+                                dev_err(&u132->platform_dev->dev, "run out of d"
+                                        "evice space\n");
+                                return -EINVAL;
+                        }
+                        urb->hcpriv = u132;
+                        if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                                endp->urb_list[ENDP_QUEUE_MASK &
+                                        endp->queue_last++] = urb;
+                        } else {
+                                struct u132_urbq *urbq =
+                                        kmalloc(sizeof(struct u132_urbq),
+                                        GFP_ATOMIC);
+                                if (urbq == NULL) {
+                                        endp->queue_size -= 1;
+                                        return -ENOMEM;
+                                } else {
+                                        list_add_tail(&urbq->urb_more,
+                                                &endp->urb_more);
+                                        urbq->urb = urb;
+                                }
+                        }
+                        return 0;
+                }
+        } else {                /*(usb_addr > 0) */
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                urb->hcpriv = u132;
+                if (udev->enumeration == 2) {
+                } else
+                        udev->enumeration = 2;
+                if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
+                        endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
+                                urb;
+                } else {
+                        struct u132_urbq *urbq =
+                                kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
+                        if (urbq == NULL) {
+                                endp->queue_size -= 1;
+                                return -ENOMEM;
+                        } else {
+                                list_add_tail(&urbq->urb_more, &endp->urb_more);
+                                urbq->urb = urb;
+                        }
+                }
+                return 0;
+        }
+}
+
+static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
+        struct urb *urb, gfp_t mem_flags)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (irqs_disabled()) {
+                if (__GFP_WAIT & mem_flags) {
+                        printk(KERN_ERR "invalid context for function that migh"
+                                "t sleep\n");
+                        return -EINVAL;
+                }
+        }
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed urb="
+                        "%p status=%d\n", urb, urb->status);
+                return -ESHUTDOWN;
+        } else {
+                u8 usb_addr = usb_pipedevice(urb->pipe);
+                u8 usb_endp = usb_pipeendpoint(urb->pipe);
+                struct usb_device *usb_dev = urb->dev;
+                if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
+                        u8 address = u132->addr[usb_addr].address;
+                        struct u132_udev *udev = &u132->udev[address];
+                        struct u132_endp *endp = hep->hcpriv;
+                        urb->actual_length = 0;
+                        if (endp) {
+                                unsigned long irqs;
+                                int retval;
+                                spin_lock_irqsave(&endp->queue_lock.slock,
+                                        irqs);
+                                retval = queue_int_on_old_endpoint(u132, udev,
+                                        hep, urb, usb_dev, endp, usb_addr,
+                                        usb_endp, address);
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                if (retval) {
+                                        return retval;
+                                } else {
+                                        u132_endp_queue_work(u132, endp,
+                                                msecs_to_jiffies(urb->interval))
+                                                ;
+                                        return 0;
+                                }
+                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                                return -EINVAL;
+                        } else {        /*(endp == NULL) */
+                                return create_endpoint_and_queue_int(u132, udev,
+                                         hep, urb, usb_dev, usb_addr, usb_endp,
+                                        address, mem_flags);
+                        }
+                } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+                        dev_err(&u132->platform_dev->dev, "the hardware does no"
+                                "t support PIPE_ISOCHRONOUS\n");
+                        return -EINVAL;
+                } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
+                        u8 address = u132->addr[usb_addr].address;
+                        struct u132_udev *udev = &u132->udev[address];
+                        struct u132_endp *endp = hep->hcpriv;
+                        urb->actual_length = 0;
+                        if (endp) {
+                                unsigned long irqs;
+                                int retval;
+                                spin_lock_irqsave(&endp->queue_lock.slock,
+                                        irqs);
+                                retval = queue_bulk_on_old_endpoint(u132, udev,
+                                        hep, urb, usb_dev, endp, usb_addr,
+                                        usb_endp, address);
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                if (retval) {
+                                        return retval;
+                                } else {
+                                        u132_endp_queue_work(u132, endp, 0);
+                                        return 0;
+                                }
+                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                                return -EINVAL;
+                        } else
+                                return create_endpoint_and_queue_bulk(u132,
+                                        udev, hep, urb, usb_dev, usb_addr,
+                                        usb_endp, address, mem_flags);
+                } else {
+                        struct u132_endp *endp = hep->hcpriv;
+                        u16 urb_size = 8;
+                        u8 *b = urb->setup_packet;
+                        int i = 0;
+                        char data[30 *3 + 4];
+                        char *d = data;
+                        int m = (sizeof(data) - 1) / 3;
+                        int l = 0;
+                        data[0] = 0;
+                        while (urb_size-- > 0) {
+                                if (i > m) {
+                                } else if (i++ < m) {
+                                        int w = sprintf(d, " %02X", *b++);
+                                        d += w;
+                                        l += w;
+                                } else
+                                        d += sprintf(d, " ..");
+                        }
+                        if (endp) {
+                                unsigned long irqs;
+                                int retval;
+                                spin_lock_irqsave(&endp->queue_lock.slock,
+                                        irqs);
+                                retval = queue_control_on_old_endpoint(u132,
+                                        hep, urb, usb_dev, endp, usb_addr,
+                                        usb_endp);
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                if (retval) {
+                                        return retval;
+                                } else {
+                                        u132_endp_queue_work(u132, endp, 0);
+                                        return 0;
+                                }
+                        } else if (u132->num_endpoints == MAX_U132_ENDPS) {
+                                return -EINVAL;
+                        } else
+                                return create_endpoint_and_queue_control(u132,
+                                        hep, urb, usb_dev, usb_addr, usb_endp,
+                                        mem_flags);
+                }
+        }
+}
+
+static int dequeue_from_overflow_chain(struct u132 *u132,
+        struct u132_endp *endp, struct urb *urb)
+{
+        struct list_head *scan;
+        struct list_head *head = &endp->urb_more;
+        list_for_each(scan, head) {
+                struct u132_urbq *urbq = list_entry(scan, struct u132_urbq,
+                        urb_more);
+                if (urbq->urb == urb) {
+                        struct usb_hcd *hcd = u132_to_hcd(u132);
+                        list_del(scan);
+                        endp->queue_size -= 1;
+                        urb->error_count = 0;
+                        urb->hcpriv = NULL;
+                        usb_hcd_giveback_urb(hcd, urb, NULL);
+                        return 0;
+                } else
+                        continue;
+        }
+        dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
+                "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
+                "\n", urb, endp->endp_number, endp, endp->ring->number,
+                endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+                endp->usb_endp, endp->usb_addr, endp->queue_size,
+                endp->queue_next, endp->queue_last);
+        return -EINVAL;
+}
+
+static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
+        struct urb *urb)
+{
+        unsigned long irqs;
+        spin_lock_irqsave(&endp->queue_lock.slock, irqs);
+        if (endp->queue_size == 0) {
+                dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
+                        "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
+                        endp->endp_number, endp, endp->ring->number,
+                        endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
+                        endp->usb_endp, endp->usb_addr);
+                spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                return -EINVAL;
+        }
+        if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
+                if (endp->active) {
+                        endp->dequeueing = 1;
+                        endp->edset_flush = 1;
+                        u132_endp_queue_work(u132, endp, 0);
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        urb->hcpriv = NULL;
+                        return 0;
+                } else {
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        u132_hcd_abandon_urb(u132, endp, urb, urb->status);
+                        return 0;
+                }
+        } else {
+                u16 queue_list = 0;
+                u16 queue_size = endp->queue_size;
+                u16 queue_scan = endp->queue_next;
+                struct urb **urb_slot = NULL;
+                while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+                        if (urb == endp->urb_list[ENDP_QUEUE_MASK &
+                                ++queue_scan]) {
+                                urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+                                        queue_scan];
+                                break;
+                        } else
+                                continue;
+                }
+                while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
+                        *urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
+                                ++queue_scan];
+                        urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
+                                queue_scan];
+                }
+                if (urb_slot) {
+                        struct usb_hcd *hcd = u132_to_hcd(u132);
+                        endp->queue_size -= 1;
+                        if (list_empty(&endp->urb_more)) {
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                        } else {
+                                struct list_head *next = endp->urb_more.next;
+                                struct u132_urbq *urbq = list_entry(next,
+                                        struct u132_urbq, urb_more);
+                                list_del(next);
+                                *urb_slot = urbq->urb;
+                                spin_unlock_irqrestore(&endp->queue_lock.slock,
+                                        irqs);
+                                kfree(urbq);
+                        } urb->error_count = 0;
+                        urb->hcpriv = NULL;
+                        usb_hcd_giveback_urb(hcd, urb, NULL);
+                        return 0;
+                } else if (list_empty(&endp->urb_more)) {
+                        dev_err(&u132->platform_dev->dev, "urb=%p not found in "
+                                "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
+                                "=%d size=%d next=%04X last=%04X\n", urb,
+                                endp->endp_number, endp, endp->ring->number,
+                                endp->input ? 'I' : ' ',
+                                endp->output ? 'O' : ' ', endp->usb_endp,
+                                endp->usb_addr, endp->queue_size,
+                                endp->queue_next, endp->queue_last);
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        return -EINVAL;
+                } else {
+                        int retval = dequeue_from_overflow_chain(u132, endp,
+                                urb);
+                        spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
+                        return retval;
+                }
+        }
+}
+
+static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 2) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else {
+                u8 usb_addr = usb_pipedevice(urb->pipe);
+                u8 usb_endp = usb_pipeendpoint(urb->pipe);
+                u8 address = u132->addr[usb_addr].address;
+                struct u132_udev *udev = &u132->udev[address];
+                if (usb_pipein(urb->pipe)) {
+                        u8 endp_number = udev->endp_number_in[usb_endp];
+                        struct u132_endp *endp = u132->endp[endp_number - 1];
+                        return u132_endp_urb_dequeue(u132, endp, urb);
+                } else {
+                        u8 endp_number = udev->endp_number_out[usb_endp];
+                        struct u132_endp *endp = u132->endp[endp_number - 1];
+                        return u132_endp_urb_dequeue(u132, endp, urb);
+                }
+        }
+}
+
+static void u132_endpoint_disable(struct usb_hcd *hcd,
+        struct usb_host_endpoint *hep)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 2) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+        } else {
+                struct u132_endp *endp = hep->hcpriv;
+                if (endp)
+                        u132_endp_put_kref(u132, endp);
+        }
+}
+
+static int u132_get_frame(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int frame = 0;
+                dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
+                msleep(100);
+                return frame;
+        }
+}
+
+static int u132_roothub_descriptor(struct u132 *u132,
+        struct usb_hub_descriptor *desc)
+{
+        int retval;
+        u16 temp;
+        u32 rh_a = -1;
+        u32 rh_b = -1;
+        retval = u132_read_pcimem(u132, roothub.a, &rh_a);
+        if (retval)
+                return retval;
+        desc->bDescriptorType = 0x29;
+        desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
+        desc->bHubContrCurrent = 0;
+        desc->bNbrPorts = u132->num_ports;
+        temp = 1 + (u132->num_ports / 8);
+        desc->bDescLength = 7 + 2 *temp;
+        temp = 0;
+        if (rh_a & RH_A_NPS)
+                temp |= 0x0002;
+        if (rh_a & RH_A_PSM)
+                temp |= 0x0001;
+        if (rh_a & RH_A_NOCP) {
+                temp |= 0x0010;
+        } else if (rh_a & RH_A_OCPM)
+                temp |= 0x0008;
+        desc->wHubCharacteristics = cpu_to_le16(temp);
+        retval = u132_read_pcimem(u132, roothub.b, &rh_b);
+        if (retval)
+                return retval;
+        memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
+        desc->bitmap[0] = rh_b & RH_B_DR;
+        if (u132->num_ports > 7) {
+                desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
+                desc->bitmap[2] = 0xff;
+        } else
+                desc->bitmap[1] = 0xff;
+        return 0;
+}
+
+static int u132_roothub_status(struct u132 *u132, __le32 *desc)
+{
+        u32 rh_status = -1;
+        int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
+        *desc = cpu_to_le32(rh_status);
+        return ret_status;
+}
+
+static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
+{
+        if (wIndex == 0 || wIndex > u132->num_ports) {
+                return -EINVAL;
+        } else {
+                int port = wIndex - 1;
+                u32 rh_portstatus = -1;
+                int ret_portstatus = u132_read_pcimem(u132,
+                        roothub.portstatus[port], &rh_portstatus);
+                *desc = cpu_to_le32(rh_portstatus);
+                if (*(u16 *) (desc + 2)) {
+                        dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
+                                "ge = %08X\n", port, *desc);
+                }
+                return ret_portstatus;
+        }
+}
+
+
+/* this timer value might be vendor-specific ... */
+#define PORT_RESET_HW_MSEC 10
+#define PORT_RESET_MSEC 10
+/* wrap-aware logic morphed from <linux/jiffies.h> */
+#define tick_before(t1, t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
+static int u132_roothub_portreset(struct u132 *u132, int port_index)
+{
+        int retval;
+        u32 fmnumber;
+        u16 now;
+        u16 reset_done;
+        retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+        if (retval)
+                return retval;
+        now = fmnumber;
+        reset_done = now + PORT_RESET_MSEC;
+        do {
+                u32 portstat;
+                do {
+                        retval = u132_read_pcimem(u132,
+                                roothub.portstatus[port_index], &portstat);
+                        if (retval)
+                                return retval;
+                        if (RH_PS_PRS & portstat) {
+                                continue;
+                        } else
+                                break;
+                } while (tick_before(now, reset_done));
+                if (RH_PS_PRS & portstat)
+                        return -ENODEV;
+                if (RH_PS_CCS & portstat) {
+                        if (RH_PS_PRSC & portstat) {
+                                retval = u132_write_pcimem(u132,
+                                        roothub.portstatus[port_index],
+                                        RH_PS_PRSC);
+                                if (retval)
+                                        return retval;
+                        }
+                } else
+                        break;        /* start the next reset,
+                                sleep till it's probably done */
+                retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+                         RH_PS_PRS);
+                if (retval)
+                        return retval;
+                msleep(PORT_RESET_HW_MSEC);
+                retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
+                if (retval)
+                        return retval;
+                now = fmnumber;
+        } while (tick_before(now, reset_done));
+        return 0;
+}
+
+static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue,
+        u16 wIndex)
+{
+        if (wIndex == 0 || wIndex > u132->num_ports) {
+                return -EINVAL;
+        } else {
+                int retval;
+                int port_index = wIndex - 1;
+                struct u132_port *port = &u132->port[port_index];
+                port->Status &= ~(1 << wValue);
+                switch (wValue) {
+                case USB_PORT_FEAT_SUSPEND:
+                        retval = u132_write_pcimem(u132,
+                                roothub.portstatus[port_index], RH_PS_PSS);
+                        if (retval)
+                                return retval;
+                        return 0;
+                case USB_PORT_FEAT_POWER:
+                        retval = u132_write_pcimem(u132,
+                                roothub.portstatus[port_index], RH_PS_PPS);
+                        if (retval)
+                                return retval;
+                        return 0;
+                case USB_PORT_FEAT_RESET:
+                        retval = u132_roothub_portreset(u132, port_index);
+                        if (retval)
+                                return retval;
+                        return 0;
+                default:
+                        return -EPIPE;
+                }
+        }
+}
+
+static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue,
+        u16 wIndex)
+{
+        if (wIndex == 0 || wIndex > u132->num_ports) {
+                return -EINVAL;
+        } else {
+                int port_index = wIndex - 1;
+                u32 temp;
+                int retval;
+                struct u132_port *port = &u132->port[port_index];
+                port->Status &= ~(1 << wValue);
+                switch (wValue) {
+                case USB_PORT_FEAT_ENABLE:
+                        temp = RH_PS_CCS;
+                        break;
+                case USB_PORT_FEAT_C_ENABLE:
+                        temp = RH_PS_PESC;
+                        break;
+                case USB_PORT_FEAT_SUSPEND:
+                        temp = RH_PS_POCI;
+                        if ((u132->hc_control & OHCI_CTRL_HCFS)
+                                != OHCI_USB_OPER) {
+                                dev_err(&u132->platform_dev->dev, "TODO resume_"
+                                        "root_hub\n");
+                        }
+                        break;
+                case USB_PORT_FEAT_C_SUSPEND:
+                        temp = RH_PS_PSSC;
+                        break;
+                case USB_PORT_FEAT_POWER:
+                        temp = RH_PS_LSDA;
+                        break;
+                case USB_PORT_FEAT_C_CONNECTION:
+                        temp = RH_PS_CSC;
+                        break;
+                case USB_PORT_FEAT_C_OVER_CURRENT:
+                        temp = RH_PS_OCIC;
+                        break;
+                case USB_PORT_FEAT_C_RESET:
+                        temp = RH_PS_PRSC;
+                        break;
+                default:
+                        return -EPIPE;
+                }
+                retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
+                         temp);
+                if (retval)
+                        return retval;
+                return 0;
+        }
+}
+
+
+/* the virtual root hub timer IRQ checks for hub status*/
+static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
+                        "ed %d\n", hcd, u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
+                        "ed\n", hcd);
+                dump_stack();
+                return -ESHUTDOWN;
+        } else {
+                int i, changed = 0, length = 1;
+                if (u132->flags & OHCI_QUIRK_AMD756) {
+                        if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
+                                dev_err(&u132->platform_dev->dev, "bogus NDP, r"
+                                        "ereads as NDP=%d\n",
+                                        u132->hc_roothub_a & RH_A_NDP);
+                                goto done;
+                        }
+                }
+                if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC)) {
+                        buf[0] = changed = 1;
+                } else
+                        buf[0] = 0;
+                if (u132->num_ports > 7) {
+                        buf[1] = 0;
+                        length++;
+                }
+                for (i = 0; i < u132->num_ports; i++) {
+                        if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
+                                RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
+                                RH_PS_PRSC)) {
+                                changed = 1;
+                                if (i < 7) {
+                                        buf[0] |= 1 << (i + 1);
+                                } else
+                                        buf[1] |= 1 << (i - 7);
+                                continue;
+                        }
+                        if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS)) {
+                                continue;
+                        }
+                        if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS)) {
+                                continue;
+                        }
+                }
+              done:return changed ? length : 0;
+        }
+}
+
+static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+        u16 wIndex, char *buf, u16 wLength)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval = 0;
+                down(&u132->sw_lock);
+                switch (typeReq) {
+                case ClearHubFeature:
+                        switch (wValue) {
+                        case C_HUB_OVER_CURRENT:
+                        case C_HUB_LOCAL_POWER:
+                                break;
+                        default:
+                                goto stall;
+                        }
+                        break;
+                case SetHubFeature:
+                        switch (wValue) {
+                        case C_HUB_OVER_CURRENT:
+                        case C_HUB_LOCAL_POWER:
+                                break;
+                        default:
+                                goto stall;
+                        }
+                        break;
+                case ClearPortFeature:{
+                                retval = u132_roothub_clearportfeature(u132,
+                                        wValue, wIndex);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case GetHubDescriptor:{
+                                retval = u132_roothub_descriptor(u132,
+                                        (struct usb_hub_descriptor *)buf);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case GetHubStatus:{
+                                retval = u132_roothub_status(u132,
+                                        (__le32 *) buf);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case GetPortStatus:{
+                                retval = u132_roothub_portstatus(u132,
+                                        (__le32 *) buf, wIndex);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                case SetPortFeature:{
+                                retval = u132_roothub_setportfeature(u132,
+                                        wValue, wIndex);
+                                if (retval)
+                                        goto error;
+                                break;
+                        }
+                default:
+                        goto stall;
+                      error:u132_disable(u132);
+                        u132->going = 1;
+                        break;
+                      stall:retval = -EPIPE;
+                        break;
+                }
+                up(&u132->sw_lock);
+                return retval;
+        }
+}
+
+static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static void u132_hub_irq_enable(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+        } else if (u132->going > 0)
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+}
+
+
+#ifdef CONFIG_PM
+static int u132_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static int u132_hcd_resume(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static int u132_bus_suspend(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+static int u132_bus_resume(struct usb_hcd *hcd)
+{
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else
+                return 0;
+}
+
+#else
+#define u132_hcd_suspend NULL
+#define u132_hcd_resume NULL
+#define u132_bus_suspend NULL
+#define u132_bus_resume NULL
+#endif
+static struct hc_driver u132_hc_driver = {
+        .description = hcd_name,
+        .hcd_priv_size = sizeof(struct u132),
+        .irq = NULL,
+        .flags = HCD_USB11 | HCD_MEMORY,
+        .reset = u132_hcd_reset,
+        .start = u132_hcd_start,
+        .suspend = u132_hcd_suspend,
+        .resume = u132_hcd_resume,
+        .stop = u132_hcd_stop,
+        .urb_enqueue = u132_urb_enqueue,
+        .urb_dequeue = u132_urb_dequeue,
+        .endpoint_disable = u132_endpoint_disable,
+        .get_frame_number = u132_get_frame,
+        .hub_status_data = u132_hub_status_data,
+        .hub_control = u132_hub_control,
+        .bus_suspend = u132_bus_suspend,
+        .bus_resume = u132_bus_resume,
+        .start_port_reset = u132_start_port_reset,
+        .hub_irq_enable = u132_hub_irq_enable,
+};
+
+/*
+* This function may be called by the USB core whilst the "usb_all_devices_rwsem"
+* is held for writing, thus this module must not call usb_remove_hcd()
+* synchronously - but instead should immediately stop activity to the
+* device and ansynchronously call usb_remove_hcd()
+*/
+static int __devexit u132_remove(struct platform_device *pdev)
+{
+        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+        if (hcd) {
+                struct u132 *u132 = hcd_to_u132(hcd);
+                dump_stack();
+                if (u132->going++ > 1) {
+                        return -ENODEV;
+                } else {
+                        int rings = MAX_U132_RINGS;
+                        int endps = MAX_U132_ENDPS;
+                        msleep(100);
+                        down(&u132->sw_lock);
+                        u132_monitor_cancel_work(u132);
+                        while (rings-- > 0) {
+                                struct u132_ring *ring = &u132->ring[rings];
+                                u132_ring_cancel_work(u132, ring);
+                        } while (endps-- > 0) {
+                                struct u132_endp *endp = u132->endp[endps];
+                                if (endp)
+                                        u132_endp_cancel_work(u132, endp);
+                        }
+                        u132->going += 1;
+                        printk(KERN_INFO "removing device u132.%d\n",
+                                u132->sequence_num);
+                        up(&u132->sw_lock);
+                        usb_remove_hcd(hcd);
+                        u132_u132_put_kref(u132);
+                        return 0;
+                }
+        } else
+                return 0;
+}
+
+static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
+{
+        int rings = MAX_U132_RINGS;
+        int ports = MAX_U132_PORTS;
+        int addrs = MAX_U132_ADDRS;
+        int udevs = MAX_U132_UDEVS;
+        int endps = MAX_U132_ENDPS;
+        u132->board = pdev->dev.platform_data;
+        u132->platform_dev = pdev;
+        u132->power = 0;
+        u132->reset = 0;
+        init_MUTEX(&u132->sw_lock);
+        init_MUTEX(&u132->scheduler_lock);
+        while (rings-- > 0) {
+                struct u132_ring *ring = &u132->ring[rings];
+                ring->u132 = u132;
+                ring->number = rings + 1;
+                ring->length = 0;
+                ring->curr_endp = NULL;
+                INIT_WORK(&ring->scheduler, u132_hcd_ring_work_scheduler,
+                        (void *)ring);
+        } down(&u132->sw_lock);
+        INIT_WORK(&u132->monitor, u132_hcd_monitor_work, (void *)u132);
+        while (ports-- > 0) {
+                struct u132_port *port = &u132->port[ports];
+                port->u132 = u132;
+                port->reset = 0;
+                port->enable = 0;
+                port->power = 0;
+                port->Status = 0;
+        } while (addrs-- > 0) {
+                struct u132_addr *addr = &u132->addr[addrs];
+                addr->address = 0;
+        } while (udevs-- > 0) {
+                struct u132_udev *udev = &u132->udev[udevs];
+                int i = ARRAY_SIZE(udev->endp_number_in);
+                int o = ARRAY_SIZE(udev->endp_number_out);
+                udev->usb_device = NULL;
+                udev->udev_number = 0;
+                udev->usb_addr = 0;
+                udev->portnumber = 0;
+                while (i-- > 0) {
+                        udev->endp_number_in[i] = 0;
+                }
+                while (o-- > 0) {
+                        udev->endp_number_out[o] = 0;
+                }
+        }
+        while (endps-- > 0) {
+                u132->endp[endps] = NULL;
+        }
+        up(&u132->sw_lock);
+        return;
+}
+
+static int __devinit u132_probe(struct platform_device *pdev)
+{
+        struct usb_hcd *hcd;
+        msleep(100);
+        if (u132_exiting > 0) {
+                return -ENODEV;
+        }                        /* refuse to confuse usbcore */
+        if (pdev->dev.dma_mask) {
+                return -EINVAL;
+        }
+        hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
+        if (!hcd) {
+                printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
+                        );
+                ftdi_elan_gone_away(pdev);
+                return -ENOMEM;
+        } else {
+                int retval = 0;
+                struct u132 *u132 = hcd_to_u132(hcd);
+                hcd->rsrc_start = 0;
+                down(&u132_module_lock);
+                list_add_tail(&u132->u132_list, &u132_static_list);
+                u132->sequence_num = ++u132_instances;
+                up(&u132_module_lock);
+                u132_u132_init_kref(u132);
+                u132_initialise(u132, pdev);
+                hcd->product_desc = "ELAN U132 Host Controller";
+                retval = usb_add_hcd(hcd, 0, 0);
+                if (retval != 0) {
+                        dev_err(&u132->platform_dev->dev, "init error %d\n",
+                                retval);
+                        u132_u132_put_kref(u132);
+                        return retval;
+                } else {
+                        u132_monitor_queue_work(u132, 100);
+                        return 0;
+                }
+        }
+}
+
+
+#ifdef CONFIG_PM
+/* for this device there's no useful distinction between the controller
+* and its root hub, except that the root hub only gets direct PM calls
+* when CONFIG_USB_SUSPEND is enabled.
+*/
+static int u132_suspend(struct platform_device *pdev, pm_message_t state)
+{
+        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval = 0;
+                if (state.event == PM_EVENT_FREEZE) {
+                        retval = u132_bus_suspend(hcd);
+                } else if (state.event == PM_EVENT_SUSPEND) {
+                        int ports = MAX_U132_PORTS;
+                        while (ports-- > 0) {
+                                port_power(u132, ports, 0);
+                        }
+                }
+                if (retval == 0)
+                        pdev->dev.power.power_state = state;
+                return retval;
+        }
+}
+
+static int u132_resume(struct platform_device *pdev)
+{
+        struct usb_hcd *hcd = platform_get_drvdata(pdev);
+        struct u132 *u132 = hcd_to_u132(hcd);
+        if (u132->going > 1) {
+                dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
+                        , u132->going);
+                return -ENODEV;
+        } else if (u132->going > 0) {
+                dev_err(&u132->platform_dev->dev, "device is being removed\n");
+                return -ESHUTDOWN;
+        } else {
+                int retval = 0;
+                if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
+                        int ports = MAX_U132_PORTS;
+                        while (ports-- > 0) {
+                                port_power(u132, ports, 1);
+                        }
+                        retval = 0;
+                } else {
+                        pdev->dev.power.power_state = PMSG_ON;
+                        retval = u132_bus_resume(hcd);
+                }
+                return retval;
+        }
+}
+
+#else
+#define u132_suspend NULL
+#define u132_resume NULL
+#endif
+/*
+* this driver is loaded explicitely by ftdi_u132
+*
+* the platform_driver struct is static because it is per type of module
+*/
+static struct platform_driver u132_platform_driver = {
+        .probe = u132_probe,
+        .remove = __devexit_p(u132_remove),
+        .suspend = u132_suspend,
+        .resume = u132_resume,
+        .driver = {
+                   .name = (char *)hcd_name,
+                   .owner = THIS_MODULE,
+                   },
+};
+static int __init u132_hcd_init(void)
+{
+        int retval;
+        INIT_LIST_HEAD(&u132_static_list);
+        u132_instances = 0;
+        u132_exiting = 0;
+        init_MUTEX(&u132_module_lock);
+        if (usb_disabled())
+                return -ENODEV;
+        printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
+                __DATE__);
+        workqueue = create_singlethread_workqueue("u132");
+        retval = platform_driver_register(&u132_platform_driver);
+        return retval;
+}
+
+
+module_init(u132_hcd_init);
+static void __exit u132_hcd_exit(void)
+{
+        struct u132 *u132;
+        struct u132 *temp;
+        down(&u132_module_lock);
+        u132_exiting += 1;
+        up(&u132_module_lock);
+        list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
+                platform_device_unregister(u132->platform_dev);
+        } platform_driver_unregister(&u132_platform_driver);
+        printk(KERN_INFO "u132-hcd driver deregistered\n");
+        wait_event(u132_hcd_wait, u132_instances == 0);
+        flush_workqueue(workqueue);
+        destroy_workqueue(workqueue);
+}
+
+
+module_exit(u132_hcd_exit);
+MODULE_LICENSE("GPL");
index dc286a48cafdeba4d687069a294a94d2980e47d1..e345f15b7d87b5e545c4d1ea0a5c9416cf38ef20 100644 (file)
@@ -16,7 +16,7 @@
 
 #include "uhci-hcd.h"
 
-#define uhci_debug_operations (* (struct file_operations *) NULL)
+#define uhci_debug_operations (* (const struct file_operations *) NULL)
 static struct dentry *uhci_debugfs_root;
 
 #ifdef DEBUG
@@ -428,7 +428,7 @@ struct uhci_debug {
 
 static int uhci_debug_open(struct inode *inode, struct file *file)
 {
-       struct uhci_hcd *uhci = inode->u.generic_ip;
+       struct uhci_hcd *uhci = inode->i_private;
        struct uhci_debug *up;
        int ret = -ENOMEM;
        unsigned long flags;
@@ -500,7 +500,7 @@ static int uhci_debug_release(struct inode *inode, struct file *file)
 }
 
 #undef uhci_debug_operations
-static struct file_operations uhci_debug_operations = {
+static const struct file_operations uhci_debug_operations = {
        .owner =        THIS_MODULE,
        .open =         uhci_debug_open,
        .llseek =       uhci_debug_lseek,
index 4151f618602d13bb801f9f2360d290c898733830..eb4eab98e8bf7ec62c1015e746f9a2e43777e852 100644 (file)
@@ -734,6 +734,10 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
 
        /* FIXME: Enable non-PME# remote wakeup? */
 
+       /* make sure snapshot being resumed re-enumerates everything */
+       if (message.event == PM_EVENT_PRETHAW)
+               uhci_hc_died(uhci);
+
 done_okay:
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 done:
@@ -909,8 +913,7 @@ static int __init uhci_hcd_init(void)
        return 0;
 
 init_failed:
-       if (kmem_cache_destroy(uhci_up_cachep))
-               warn("not all urb_privs were freed!");
+       kmem_cache_destroy(uhci_up_cachep);
 
 up_failed:
        debugfs_remove(uhci_debugfs_root);
@@ -926,10 +929,7 @@ errbuf_failed:
 static void __exit uhci_hcd_cleanup(void) 
 {
        pci_unregister_driver(&uhci_pci_driver);
-       
-       if (kmem_cache_destroy(uhci_up_cachep))
-               warn("not all urb_privs were freed!");
-
+       kmem_cache_destroy(uhci_up_cachep);
        debugfs_remove(uhci_debugfs_root);
        kfree(errbuf);
 }
index c545ef92fe29ad130a7b1de0088a945e4bd29751..16fb72eb6fc9213785216414293d7f27dedd8546 100644 (file)
@@ -84,6 +84,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
                unsigned long port_addr)
 {
        int status;
+       int i;
 
        if (inw(port_addr) & (USBPORTSC_SUSP | USBPORTSC_RD)) {
                CLR_RH_PORTSTAT(USBPORTSC_SUSP | USBPORTSC_RD);
@@ -92,9 +93,14 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port,
 
                /* The controller won't actually turn off the RD bit until
                 * it has had a chance to send a low-speed EOP sequence,
-                * which takes 3 bit times (= 2 microseconds).  We'll delay
-                * slightly longer for good luck. */
-               udelay(4);
+                * which is supposed to take 3 bit times (= 2 microseconds).
+                * Experiments show that some controllers take longer, so
+                * we'll poll for completion. */
+               for (i = 0; i < 10; ++i) {
+                       if (!(inw(port_addr) & USBPORTSC_RD))
+                               break;
+                       udelay(1);
+               }
        }
        clear_bit(port, &uhci->resuming_ports);
 }
index 08daf400f9854c9b19029c74d1534a0f64dade0a..ca6305c1d64c67ba7b529ec2b8db2fa6a1ee0f3d 100644 (file)
@@ -424,7 +424,7 @@ static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res)
  ***************************************************************************/
 
 static struct usb_driver mdc800_usb_driver;
-static struct file_operations mdc800_device_ops;
+static const struct file_operations mdc800_device_ops;
 static struct usb_class_driver mdc800_class = {
        .name =         "mdc800%d",
        .fops =         &mdc800_device_ops,
@@ -941,7 +941,7 @@ static ssize_t mdc800_device_write (struct file *file, const char __user *buf, s
 ****************************************************************************/
 
 /* File Operations of this drivers */
-static struct file_operations mdc800_device_ops =
+static const struct file_operations mdc800_device_ops =
 {
        .owner =        THIS_MODULE,
        .read =         mdc800_device_read,
index 650103bc9618434ad769972ebb6db5e8cf76ae01..a102a58fe3612c89589817dadcdd9b6c566d5cf4 100644 (file)
@@ -205,10 +205,12 @@ config USB_TOUCHSCREEN
        depends on USB && INPUT
        ---help---
          USB Touchscreen driver for:
-         - eGalax Touchkit USB
+         - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700)
          - PanJit TouchSet USB
-         - 3M MicroTouch USB
+         - 3M MicroTouch USB (EX II series)
          - ITM
+         - some other eTurboTouch
+         - Gunze AHL61
 
          Have a look at <http://linux.chapter7.ch/touchkit/> for
          a usage description and the required user-space stuff.
@@ -218,7 +220,7 @@ config USB_TOUCHSCREEN
 
 config USB_TOUCHSCREEN_EGALAX
        default y
-       bool "eGalax device support" if EMBEDDED
+       bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
        depends on USB_TOUCHSCREEN
 
 config USB_TOUCHSCREEN_PANJIT
@@ -228,7 +230,7 @@ config USB_TOUCHSCREEN_PANJIT
 
 config USB_TOUCHSCREEN_3M
        default y
-       bool "3M/Microtouch device support" if EMBEDDED
+       bool "3M/Microtouch EX II series device support" if EMBEDDED
        depends on USB_TOUCHSCREEN
 
 config USB_TOUCHSCREEN_ITM
@@ -236,6 +238,16 @@ config USB_TOUCHSCREEN_ITM
        bool "ITM device support" if EMBEDDED
        depends on USB_TOUCHSCREEN
 
+config USB_TOUCHSCREEN_ETURBO
+       default y
+       bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED
+       depends on USB_TOUCHSCREEN
+
+config USB_TOUCHSCREEN_GUNZE
+       default y
+       bool "Gunze AHL61 device support" if EMBEDDED
+       depends on USB_TOUCHSCREEN
+
 config USB_YEALINK
        tristate "Yealink usb-p1k voip phone"
        depends on USB && INPUT && EXPERIMENTAL
@@ -326,3 +338,13 @@ config USB_APPLETOUCH
 
          To compile this driver as a module, choose M here: the
          module will be called appletouch.
+
+config USB_TRANCEVIBRATOR
+       tristate "PlayStation 2 Trance Vibrator driver support"
+       depends on USB
+       help
+         Say Y here if you want to connect a PlayStation 2 Trance Vibrator
+         device to your computer's USB port.
+
+         To compile this driver as a module, choose M here: the
+         module will be called trancevibrator.
index 764114529c56af10071d2dfa94f21717edf34e18..48551be324ac61fb102a530fcd34ad0205fbed57 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 # Multipart objects.
+wacom-objs     := wacom_sys.o wacom_wac.o
 usbhid-objs    := hid-core.o
 
 # Optional parts of multipart objects.
@@ -44,6 +45,7 @@ obj-$(CONFIG_USB_ACECAD)      += acecad.o
 obj-$(CONFIG_USB_YEALINK)      += yealink.o
 obj-$(CONFIG_USB_XPAD)         += xpad.o
 obj-$(CONFIG_USB_APPLETOUCH)   += appletouch.o
+obj-$(CONFIG_USB_TRANCEVIBRATOR)       += trancevibrator.o
 
 ifeq ($(CONFIG_USB_DEBUG),y)
 EXTRA_CFLAGS += -DDEBUG
index 18c10e150ef37df3e2e78878dace708f4a9bba37..d83603ba40ae257aa344b5f7774c8a926e9789b5 100644 (file)
@@ -141,10 +141,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_
 
        endpoint = &interface->endpoint[0].desc;
 
-       if (!(endpoint->bEndpointAddress & 0x80))
-               return -ENODEV;
-
-       if ((endpoint->bmAttributes & 3) != 3)
+       if (!usb_endpoint_is_int_in(endpoint))
                return -ENODEV;
 
        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
index 044faa07e2976f49bf81bf8514f4c3b4575babbe..0aa9cc2bfd69fb5a067beaeb9664aea005abf4e3 100644 (file)
@@ -436,10 +436,7 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
        iface_desc = iface->cur_altsetting;
        for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
                endpoint = &iface_desc->endpoint[i].desc;
-               if (!int_in_endpointAddr &&
-                   (endpoint->bEndpointAddress & USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                                       == USB_ENDPOINT_XFER_INT)) {
+               if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
                        /* we found an interrupt in endpoint */
                        int_in_endpointAddr = endpoint->bEndpointAddress;
                        break;
index 3719fcb04b8f4bb01973f6dea86d4918e3dd1433..3558d7ed99b96e9cafdce2ea5002fb74ed4292e2 100644 (file)
@@ -732,12 +732,8 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
        endpoint_in = &iface_host->endpoint[0].desc;
        endpoint_out = &iface_host->endpoint[1].desc;
 
-       if (!(endpoint_in->bEndpointAddress & USB_DIR_IN)) {
-               err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__);
-               return -ENODEV;
-       }
-       if ((endpoint_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) {
-               err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__);
+       if (!usb_endpoint_is_int_in(endpoint_in)) {
+               err("%s: Unexpected endpoint_in\n", __FUNCTION__);
                return -ENODEV;
        }
        if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
index 3305fb6079eb1d968bd8a3ee4357b6d3be2c7f74..2a3e9e9b4b3dc73b2b7d0e801506e21b8040d1a9 100644 (file)
@@ -1023,7 +1023,8 @@ static void hid_irq_in(struct urb *urb, struct pt_regs *regs)
                        return;
                case -EILSEQ:           /* protocol error or unplug */
                case -EPROTO:           /* protocol error or unplug */
-               case -ETIMEDOUT:        /* NAK */
+               case -ETIME:            /* protocol error or unplug */
+               case -ETIMEDOUT:        /* Should never happen, but... */
                        clear_bit(HID_IN_RUNNING, &hid->iofl);
                        hid_io_error(hid);
                        return;
@@ -1535,13 +1536,17 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_VENDOR_ID_GLAB             0x06c2
 #define USB_DEVICE_ID_4_PHIDGETSERVO_30        0x0038
 #define USB_DEVICE_ID_1_PHIDGETSERVO_30        0x0039
-#define USB_DEVICE_ID_8_8_8_IF_KIT     0x0045
 #define USB_DEVICE_ID_0_0_4_IF_KIT     0x0040
+#define USB_DEVICE_ID_0_16_16_IF_KIT   0x0044
+#define USB_DEVICE_ID_8_8_8_IF_KIT     0x0045
+#define USB_DEVICE_ID_0_8_7_IF_KIT     0x0051
 #define USB_DEVICE_ID_0_8_8_IF_KIT     0x0053
+#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL     0x0058
 
 #define USB_VENDOR_ID_WISEGROUP                0x0925
 #define USB_DEVICE_ID_1_PHIDGETSERVO_20        0x8101
 #define USB_DEVICE_ID_4_PHIDGETSERVO_20        0x8104
+#define USB_DEVICE_ID_8_8_4_IF_KIT     0x8201
 #define USB_DEVICE_ID_DUAL_USB_JOYPAD   0x8866
 
 #define USB_VENDOR_ID_WISEGROUP_LTD    0x6677
@@ -1591,6 +1596,10 @@ void hid_init_reports(struct hid_device *hid)
 
 #define USB_VENDOR_ID_YEALINK          0x6993
 #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K      0xb001
+
+#define USB_VENDOR_ID_ALCOR            0x058f
+#define USB_DEVICE_ID_ALCOR_USBRS232   0x9720
+
 /*
  * Alphabetically sorted blacklist by quirk type.
  */
@@ -1608,6 +1617,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
@@ -1620,9 +1630,12 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
-       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
@@ -1690,7 +1703,11 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 30, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 100, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 108, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 118, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 200, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
@@ -1701,6 +1718,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K, HID_QUIRK_IGNORE },
 
        { USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
index f6b839c257a7a0f33cddaafb0c7496d7b6cb28a6..a2b419d13740e08631c3f170c52f2a642c3a2a23 100644 (file)
@@ -722,7 +722,7 @@ inval:
        return -EINVAL;
 }
 
-static struct file_operations hiddev_fops = {
+static const struct file_operations hiddev_fops = {
        .owner =        THIS_MODULE,
        .read =         hiddev_read,
        .write =        hiddev_write,
index 86acb5f1907aeebe10e644a53dc37ea02e2781ac..61966d719ca3c577e7c8f4cdbe2999da6dbac0f9 100644 (file)
@@ -87,7 +87,7 @@ static void itmtouch_irq(struct urb *urb, struct pt_regs *regs)
        case 0:
                /* success */
                break;
-       case -ETIMEDOUT:
+       case -ETIME:
                /* this urb is timing out */
                dbg("%s - urb timed out - was the device unplugged?",
                    __FUNCTION__);
index 4723b310f277e5358dfeb7445c92b790789af013..a903595515759b9f9dd19203758c07a37bb2616e 100644 (file)
@@ -420,8 +420,7 @@ static struct usb_endpoint_descriptor *keyspan_get_in_endpoint(struct usb_host_i
        for (i = 0; i < iface->desc.bNumEndpoints; ++i) {
                endpoint = &iface->endpoint[i].desc;
 
-               if ((endpoint->bEndpointAddress & USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+               if (usb_endpoint_is_int_in(endpoint)) {
                        /* we found our interrupt in endpoint */
                        return endpoint;
                }
index a9ccda8810e00af0fddd555c5326b587efeafeed..5dce951f2751a2eeb8d0a3a2bff79765d924cbca 100644 (file)
@@ -107,7 +107,7 @@ static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs)
        case 0:
                /* success */
                break;
-       case -ETIMEDOUT:
+       case -ETIME:
                /* this urb is timing out */
                dbg("%s - urb timed out - was the device unplugged?",
                    __FUNCTION__);
index b3c0d0c3eae998b45ab1de1344fe935ee9b3c95d..f0f8db6810a2900aa6160acf70d1dff75834f7f1 100644 (file)
@@ -313,9 +313,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
 
        interface = intf->cur_altsetting;
        endpoint = &interface->endpoint[0].desc;
-       if (!(endpoint->bEndpointAddress & 0x80))
-               return -EIO;
-       if ((endpoint->bmAttributes & 3) != 3)
+       if (!usb_endpoint_is_int_in(endpoint))
                return -EIO;
 
        usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
index 0149043ffb975366b6e41cc3522734773c83ee32..30b9f820e7a894e7b1db04ec347483b5177d3735 100644 (file)
@@ -201,7 +201,7 @@ static void touchkit_irq(struct urb *urb, struct pt_regs *regs)
        case 0:
                /* success */
                break;
-       case -ETIMEDOUT:
+       case -ETIME:
                /* this urb is timing out */
                dbg("%s - urb timed out - was the device unplugged?",
                    __FUNCTION__);
diff --git a/drivers/usb/input/trancevibrator.c b/drivers/usb/input/trancevibrator.c
new file mode 100644 (file)
index 0000000..33cd91d
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * PlayStation 2 Trance Vibrator driver
+ *
+ * Copyright (C) 2006 Sam Hocevar <sam@zoy.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free 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.
+ */
+
+/* Standard include files */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+/* Version Information */
+#define DRIVER_VERSION "v1.1"
+#define DRIVER_AUTHOR "Sam Hocevar, sam@zoy.org"
+#define DRIVER_DESC "PlayStation 2 Trance Vibrator driver"
+
+#define TRANCEVIBRATOR_VENDOR_ID       0x0b49  /* ASCII Corporation */
+#define TRANCEVIBRATOR_PRODUCT_ID      0x064f  /* Trance Vibrator */
+
+static struct usb_device_id id_table [] = {
+       { USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) },
+       { },
+};
+MODULE_DEVICE_TABLE (usb, id_table);
+
+/* Driver-local specific stuff */
+struct trancevibrator {
+       struct usb_device *udev;
+       unsigned int speed;
+};
+
+static ssize_t show_speed(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct trancevibrator *tv = usb_get_intfdata(intf);
+
+       return sprintf(buf, "%d\n", tv->speed);
+}
+
+static ssize_t set_speed(struct device *dev, struct device_attribute *attr,
+                        const char *buf, size_t count)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct trancevibrator *tv = usb_get_intfdata(intf);
+       int temp, retval;
+
+       temp = simple_strtoul(buf, NULL, 10);
+       if (temp > 255)
+               temp = 255;
+       else if (temp < 0)
+               temp = 0;
+       tv->speed = temp;
+
+       dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed);
+
+       /* Set speed */
+       retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0),
+                                0x01, /* vendor request: set speed */
+                                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+                                tv->speed, /* speed value */
+                                0, NULL, 0, USB_CTRL_GET_TIMEOUT);
+       if (retval) {
+               dev_dbg(&tv->udev->dev, "retval = %d\n", retval);
+               return retval;
+       }
+       return count;
+}
+
+static DEVICE_ATTR(speed, S_IWUGO | S_IRUGO, show_speed, set_speed);
+
+static int tv_probe(struct usb_interface *interface,
+                   const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(interface);
+       struct trancevibrator *dev;
+       int retval;
+
+       dev = kzalloc(sizeof(struct trancevibrator), GFP_KERNEL);
+       if (dev == NULL) {
+               dev_err(&interface->dev, "Out of memory\n");
+               retval = -ENOMEM;
+               goto error;
+       }
+
+       dev->udev = usb_get_dev(udev);
+       usb_set_intfdata(interface, dev);
+       retval = device_create_file(&interface->dev, &dev_attr_speed);
+       if (retval)
+               goto error_create_file;
+
+       return 0;
+
+error_create_file:
+       usb_put_dev(udev);
+       usb_set_intfdata(interface, NULL);
+error:
+       kfree(dev);
+       return retval;
+}
+
+static void tv_disconnect(struct usb_interface *interface)
+{
+       struct trancevibrator *dev;
+
+       dev = usb_get_intfdata (interface);
+       usb_set_intfdata(interface, NULL);
+       device_remove_file(&interface->dev, &dev_attr_speed);
+       usb_put_dev(dev->udev);
+       kfree(dev);
+}
+
+/* USB subsystem object */
+static struct usb_driver tv_driver = {
+       .name =         "trancevibrator",
+       .probe =        tv_probe,
+       .disconnect =   tv_disconnect,
+       .id_table =     id_table,
+};
+
+static int __init tv_init(void)
+{
+       int retval = usb_register(&tv_driver);
+       if (retval) {
+               err("usb_register failed. Error number %d", retval);
+               return retval;
+       }
+
+       info(DRIVER_VERSION ":" DRIVER_DESC);
+       return 0;
+}
+
+static void __exit tv_exit(void)
+{
+       usb_deregister(&tv_driver);
+}
+
+module_init (tv_init);
+module_exit (tv_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
index 446935b671d989e72e270752fffa77e33a5348ae..0fb792be95efa9edc2defe878255d29db8490e9a 100644 (file)
@@ -218,7 +218,7 @@ static void usb_mouse_disconnect(struct usb_interface *intf)
 
 static struct usb_device_id usb_mouse_id_table [] = {
        { USB_INTERFACE_INFO(3, 1, 2) },
-    { }                                                /* Terminating entry */
+       { }     /* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
index a338bf4c2d78eda0cf50ed02b55f240f5e3932b6..4640d1000d83c024f54c80876536c62ee61de6dd 100644 (file)
@@ -2,9 +2,12 @@
  * usbtouchscreen.c
  * Driver for USB Touchscreens, supporting those devices:
  *  - eGalax Touchkit
- *  - 3M/Microtouch
+ *    includes eTurboTouch CT-410/510/700
+ *  - 3M/Microtouch  EX II series
  *  - ITM
  *  - PanJit TouchSet
+ *  - eTurboTouch
+ *  - Gunze AHL61
  *
  * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
  * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@@ -42,7 +45,7 @@
 #include <linux/usb/input.h>
 
 
-#define DRIVER_VERSION         "v0.3"
+#define DRIVER_VERSION         "v0.4"
 #define DRIVER_AUTHOR          "Daniel Ritz <daniel.ritz@gmx.ch>"
 #define DRIVER_DESC            "USB Touchscreen Driver"
 
@@ -60,6 +63,7 @@ struct usbtouch_device_info {
        int flags;
 
        void (*process_pkt) (struct usbtouch_usb *usbtouch, struct pt_regs *regs, unsigned char *pkt, int len);
+       int  (*get_pkt_len) (unsigned char *pkt, int len);
        int  (*read_data)   (unsigned char *pkt, int *x, int *y, int *touch, int *press);
        int  (*init)        (struct usbtouch_usb *usbtouch);
 };
@@ -81,8 +85,16 @@ struct usbtouch_usb {
        char phys[64];
 };
 
-static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
-                                 struct pt_regs *regs, unsigned char *pkt, int len);
+
+#if defined(CONFIG_USB_TOUCHSCREEN_EGALAX) || defined(CONFIG_USB_TOUCHSCREEN_ETURBO)
+#define MULTI_PACKET
+#endif
+
+#ifdef MULTI_PACKET
+static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
+                                   struct pt_regs *regs,
+                                   unsigned char *pkt, int len);
+#endif
 
 /* device types */
 enum {
@@ -91,14 +103,19 @@ enum {
        DEVTYPE_PANJIT,
        DEVTYPE_3M,
        DEVTYPE_ITM,
+       DEVTYPE_ETURBO,
+       DEVTYPE_GUNZE,
 };
 
 static struct usb_device_id usbtouch_devices[] = {
 #ifdef CONFIG_USB_TOUCHSCREEN_EGALAX
        {USB_DEVICE(0x3823, 0x0001), .driver_info = DEVTYPE_EGALAX},
+       {USB_DEVICE(0x3823, 0x0002), .driver_info = DEVTYPE_EGALAX},
        {USB_DEVICE(0x0123, 0x0001), .driver_info = DEVTYPE_EGALAX},
        {USB_DEVICE(0x0eef, 0x0001), .driver_info = DEVTYPE_EGALAX},
        {USB_DEVICE(0x0eef, 0x0002), .driver_info = DEVTYPE_EGALAX},
+       {USB_DEVICE(0x1234, 0x0001), .driver_info = DEVTYPE_EGALAX},
+       {USB_DEVICE(0x1234, 0x0002), .driver_info = DEVTYPE_EGALAX},
 #endif
 
 #ifdef CONFIG_USB_TOUCHSCREEN_PANJIT
@@ -116,6 +133,14 @@ static struct usb_device_id usbtouch_devices[] = {
        {USB_DEVICE(0x0403, 0xf9e9), .driver_info = DEVTYPE_ITM},
 #endif
 
+#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+       {USB_DEVICE(0x1234, 0x5678), .driver_info = DEVTYPE_ETURBO},
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+       {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
+#endif
+
        {}
 };
 
@@ -140,82 +165,23 @@ static int egalax_read_data(unsigned char *pkt, int *x, int *y, int *touch, int
        *touch = pkt[0] & 0x01;
 
        return 1;
-
 }
 
-static int egalax_get_pkt_len(unsigned char *buf)
+static int egalax_get_pkt_len(unsigned char *buf, int len)
 {
        switch (buf[0] & EGALAX_PKT_TYPE_MASK) {
        case EGALAX_PKT_TYPE_REPT:
                return 5;
 
        case EGALAX_PKT_TYPE_DIAG:
+               if (len < 2)
+                       return -1;
+
                return buf[1] + 2;
        }
 
        return 0;
 }
-
-static void egalax_process(struct usbtouch_usb *usbtouch, struct pt_regs *regs,
-                           unsigned char *pkt, int len)
-{
-       unsigned char *buffer;
-       int pkt_len, buf_len, pos;
-
-       /* if the buffer contains data, append */
-       if (unlikely(usbtouch->buf_len)) {
-               int tmp;
-
-               /* if only 1 byte in buffer, add another one to get length */
-               if (usbtouch->buf_len == 1)
-                       usbtouch->buffer[1] = pkt[0];
-
-               pkt_len = egalax_get_pkt_len(usbtouch->buffer);
-
-               /* unknown packet: drop everything */
-               if (!pkt_len)
-                       return;
-
-               /* append, process */
-               tmp = pkt_len - usbtouch->buf_len;
-               memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
-               usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len);
-
-               buffer = pkt + tmp;
-               buf_len = len - tmp;
-       } else {
-               buffer = pkt;
-               buf_len = len;
-       }
-
-       /* only one byte left in buffer */
-       if (unlikely(buf_len == 1)) {
-               usbtouch->buffer[0] = buffer[0];
-               usbtouch->buf_len = 1;
-               return;
-       }
-
-       /* loop over the buffer */
-       pos = 0;
-       while (pos < buf_len) {
-               /* get packet len */
-               pkt_len = egalax_get_pkt_len(buffer + pos);
-
-               /* unknown packet: drop everything */
-               if (unlikely(!pkt_len))
-                       return;
-
-               /* full packet: process */
-               if (likely(pkt_len <= buf_len)) {
-                       usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
-               } else {
-                       /* incomplete packet: save in buffer */
-                       memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
-                       usbtouch->buf_len = buf_len - pos;
-               }
-               pos += pkt_len;
-       }
-}
 #endif
 
 
@@ -254,7 +220,7 @@ static int mtouch_read_data(unsigned char *pkt, int *x, int *y, int *touch, int
 
 static int mtouch_init(struct usbtouch_usb *usbtouch)
 {
-       int ret;
+       int ret, i;
 
        ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
                              MTOUCHUSB_RESET,
@@ -264,15 +230,20 @@ static int mtouch_init(struct usbtouch_usb *usbtouch)
            __FUNCTION__, ret);
        if (ret < 0)
                return ret;
-
-       ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
-                             MTOUCHUSB_ASYNC_REPORT,
-                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
-       dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
-           __FUNCTION__, ret);
-       if (ret < 0)
-               return ret;
+       msleep(150);
+
+       for (i = 0; i < 3; i++) {
+               ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0),
+                                     MTOUCHUSB_ASYNC_REPORT,
+                                     USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                                     1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT);
+               dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
+                   __FUNCTION__, ret);
+               if (ret >= 0)
+                       break;
+               if (ret != -EPIPE)
+                       return ret;
+       }
 
        return 0;
 }
@@ -295,6 +266,54 @@ static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *pr
 #endif
 
 
+/*****************************************************************************
+ * eTurboTouch part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+static int eturbo_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+       unsigned int shift;
+
+       /* packets should start with sync */
+       if (!(pkt[0] & 0x80))
+               return 0;
+
+       shift = (6 - (pkt[0] & 0x03));
+       *x = ((pkt[3] << 7) | pkt[4]) >> shift;
+       *y = ((pkt[1] << 7) | pkt[2]) >> shift;
+       *touch = (pkt[0] & 0x10) ? 1 : 0;
+
+       return 1;
+}
+
+static int eturbo_get_pkt_len(unsigned char *buf, int len)
+{
+       if (buf[0] & 0x80)
+               return 5;
+       if (buf[0] == 0x01)
+               return 3;
+       return 0;
+}
+#endif
+
+
+/*****************************************************************************
+ * Gunze part
+ */
+#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
+{
+       if (!(pkt[0] & 0x80) || ((pkt[1] | pkt[2] | pkt[3]) & 0x80))
+               return 0;
+
+       *x = ((pkt[0] & 0x1F) << 7) | (pkt[2] & 0x7F);
+       *y = ((pkt[1] & 0x1F) << 7) | (pkt[3] & 0x7F);
+       *touch = pkt[0] & 0x20;
+
+       return 1;
+}
+#endif
+
 /*****************************************************************************
  * the different device descriptors
  */
@@ -307,7 +326,8 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
                .max_yc         = 0x07ff,
                .rept_size      = 16,
                .flags          = USBTOUCH_FLG_BUFFER,
-               .process_pkt    = egalax_process,
+               .process_pkt    = usbtouch_process_multi,
+               .get_pkt_len    = egalax_get_pkt_len,
                .read_data      = egalax_read_data,
        },
 #endif
@@ -346,6 +366,31 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
                .read_data      = itm_read_data,
        },
 #endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_ETURBO
+       [DEVTYPE_ETURBO] = {
+               .min_xc         = 0x0,
+               .max_xc         = 0x07ff,
+               .min_yc         = 0x0,
+               .max_yc         = 0x07ff,
+               .rept_size      = 8,
+               .flags          = USBTOUCH_FLG_BUFFER,
+               .process_pkt    = usbtouch_process_multi,
+               .get_pkt_len    = eturbo_get_pkt_len,
+               .read_data      = eturbo_read_data,
+       },
+#endif
+
+#ifdef CONFIG_USB_TOUCHSCREEN_GUNZE
+       [DEVTYPE_GUNZE] = {
+               .min_xc         = 0x0,
+               .max_xc         = 0x0fff,
+               .min_yc         = 0x0,
+               .max_yc         = 0x0fff,
+               .rept_size      = 4,
+               .read_data      = gunze_read_data,
+       },
+#endif
 };
 
 
@@ -377,6 +422,83 @@ static void usbtouch_process_pkt(struct usbtouch_usb *usbtouch,
 }
 
 
+#ifdef MULTI_PACKET
+static void usbtouch_process_multi(struct usbtouch_usb *usbtouch,
+                                   struct pt_regs *regs,
+                                   unsigned char *pkt, int len)
+{
+       unsigned char *buffer;
+       int pkt_len, pos, buf_len, tmp;
+
+       /* process buffer */
+       if (unlikely(usbtouch->buf_len)) {
+               /* try to get size */
+               pkt_len = usbtouch->type->get_pkt_len(
+                               usbtouch->buffer, usbtouch->buf_len);
+
+               /* drop? */
+               if (unlikely(!pkt_len))
+                       goto out_flush_buf;
+
+               /* need to append -pkt_len bytes before able to get size */
+               if (unlikely(pkt_len < 0)) {
+                       int append = -pkt_len;
+                       if (unlikely(append > len))
+                              append = len;
+                       if (usbtouch->buf_len + append >= usbtouch->type->rept_size)
+                               goto out_flush_buf;
+                       memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, append);
+                       usbtouch->buf_len += append;
+
+                       pkt_len = usbtouch->type->get_pkt_len(
+                                       usbtouch->buffer, usbtouch->buf_len);
+                       if (pkt_len < 0)
+                               return;
+               }
+
+               /* append */
+               tmp = pkt_len - usbtouch->buf_len;
+               if (usbtouch->buf_len + tmp >= usbtouch->type->rept_size)
+                       goto out_flush_buf;
+               memcpy(usbtouch->buffer + usbtouch->buf_len, pkt, tmp);
+               usbtouch_process_pkt(usbtouch, regs, usbtouch->buffer, pkt_len);
+
+               buffer = pkt + tmp;
+               buf_len = len - tmp;
+       } else {
+               buffer = pkt;
+               buf_len = len;
+       }
+
+       /* loop over the received packet, process */
+       pos = 0;
+       while (pos < buf_len) {
+               /* get packet len */
+               pkt_len = usbtouch->type->get_pkt_len(buffer + pos, len);
+
+               /* unknown packet: drop everything */
+               if (unlikely(!pkt_len))
+                       goto out_flush_buf;
+
+               /* full packet: process */
+               if (likely((pkt_len > 0) && (pkt_len <= buf_len - pos))) {
+                       usbtouch_process_pkt(usbtouch, regs, buffer + pos, pkt_len);
+               } else {
+                       /* incomplete packet: save in buffer */
+                       memcpy(usbtouch->buffer, buffer + pos, buf_len - pos);
+                       usbtouch->buf_len = buf_len - pos;
+                       return;
+               }
+               pos += pkt_len;
+       }
+
+out_flush_buf:
+       usbtouch->buf_len = 0;
+       return;
+}
+#endif
+
+
 static void usbtouch_irq(struct urb *urb, struct pt_regs *regs)
 {
        struct usbtouch_usb *usbtouch = urb->context;
@@ -386,7 +508,7 @@ static void usbtouch_irq(struct urb *urb, struct pt_regs *regs)
        case 0:
                /* success */
                break;
-       case -ETIMEDOUT:
+       case -ETIME:
                /* this urb is timing out */
                dbg("%s - urb timed out - was the device unplugged?",
                    __FUNCTION__);
@@ -452,7 +574,7 @@ static int usbtouch_probe(struct usb_interface *intf,
        struct usb_endpoint_descriptor *endpoint;
        struct usb_device *udev = interface_to_usbdev(intf);
        struct usbtouch_device_info *type;
-       int err;
+       int err = -ENOMEM;
 
        interface = intf->cur_altsetting;
        endpoint = &interface->endpoint[0].desc;
@@ -526,6 +648,7 @@ static int usbtouch_probe(struct usb_interface *intf,
                         usbtouch->data, type->rept_size,
                         usbtouch_irq, usbtouch, endpoint->bInterval);
 
+       usbtouch->irq->dev = usbtouch->udev;
        usbtouch->irq->transfer_dma = usbtouch->data_dma;
        usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
@@ -553,7 +676,7 @@ out_free_buffers:
 out_free:
        input_free_device(input_dev);
        kfree(usbtouch);
-       return -ENOMEM;
+       return err;
 }
 
 static void usbtouch_disconnect(struct usb_interface *intf)
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
deleted file mode 100644 (file)
index 369461a..0000000
+++ /dev/null
@@ -1,1003 +0,0 @@
-/*
- *  USB Wacom Graphire and Wacom Intuos tablet support
- *
- *  Copyright (c) 2000-2004 Vojtech Pavlik     <vojtech@ucw.cz>
- *  Copyright (c) 2000 Andreas Bach Aaen       <abach@stofanet.dk>
- *  Copyright (c) 2000 Clifford Wolf           <clifford@clifford.at>
- *  Copyright (c) 2000 Sam Mosel               <sam.mosel@computer.org>
- *  Copyright (c) 2000 James E. Blair          <corvus@gnu.org>
- *  Copyright (c) 2000 Daniel Egger            <egger@suse.de>
- *  Copyright (c) 2001 Frederic Lepied         <flepied@mandrakesoft.com>
- *  Copyright (c) 2004 Panagiotis Issaris      <panagiotis.issaris@mech.kuleuven.ac.be>
- *  Copyright (c) 2002-2006 Ping Cheng         <pingc@wacom.com>
- *
- *  ChangeLog:
- *      v0.1 (vp)  - Initial release
- *      v0.2 (aba) - Support for all buttons / combinations
- *      v0.3 (vp)  - Support for Intuos added
- *     v0.4 (sm)  - Support for more Intuos models, menustrip
- *                     relative mode, proximity.
- *     v0.5 (vp)  - Big cleanup, nifty features removed,
- *                     they belong in userspace
- *     v1.8 (vp)  - Submit URB only when operating, moved to CVS,
- *                     use input_report_key instead of report_btn and
- *                     other cleanups
- *     v1.11 (vp) - Add URB ->dev setting for new kernels
- *     v1.11 (jb) - Add support for the 4D Mouse & Lens
- *     v1.12 (de) - Add support for two more inking pen IDs
- *     v1.14 (vp) - Use new USB device id probing scheme.
- *                  Fix Wacom Graphire mouse wheel
- *     v1.18 (vp) - Fix mouse wheel direction
- *                  Make mouse relative
- *      v1.20 (fl) - Report tool id for Intuos devices
- *                 - Multi tools support
- *                 - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
- *                 - Add PL models support
- *                - Fix Wacom Graphire mouse wheel again
- *     v1.21 (vp) - Removed protocol descriptions
- *                - Added MISC_SERIAL for tool serial numbers
- *           (gb) - Identify version on module load.
- *    v1.21.1 (fl) - added Graphire2 support
- *    v1.21.2 (fl) - added Intuos2 support
- *                 - added all the PL ids
- *    v1.21.3 (fl) - added another eraser id from Neil Okamoto
- *                 - added smooth filter for Graphire from Peri Hankey
- *                 - added PenPartner support from Olaf van Es
- *                 - new tool ids from Ole Martin Bjoerndalen
- *     v1.29 (pc) - Add support for more tablets
- *                - Fix pressure reporting
- *     v1.30 (vp) - Merge 2.4 and 2.5 drivers
- *                - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
- *                - Cleanups here and there
- *    v1.30.1 (pi) - Added Graphire3 support
- *     v1.40 (pc) - Add support for several new devices, fix eraser reporting, ...
- *     v1.43 (pc) - Added support for Cintiq 21UX
- *                - Fixed a Graphire bug
- *                - Merged wacom_intuos3_irq into wacom_intuos_irq
- *     v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc.
- *                - Report Device IDs
- *     v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19
- *                - Minor data report fix
- */
-
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/usb/input.h>
-#include <asm/unaligned.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.45"
-#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
-#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
-#define DRIVER_LICENSE "GPL"
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE(DRIVER_LICENSE);
-
-#define USB_VENDOR_ID_WACOM    0x056a
-#define STYLUS_DEVICE_ID       0x02
-#define CURSOR_DEVICE_ID       0x06
-#define ERASER_DEVICE_ID       0x0A
-
-enum {
-       PENPARTNER = 0,
-       GRAPHIRE,
-       WACOM_G4,
-       PL,
-       INTUOS,
-       INTUOS3,
-       INTUOS312,
-       INTUOS319,
-       CINTIQ,
-       MAX_TYPE
-};
-
-struct wacom_features {
-       char *name;
-       int pktlen;
-       int x_max;
-       int y_max;
-       int pressure_max;
-       int distance_max;
-       int type;
-       usb_complete_t irq;
-};
-
-struct wacom {
-       signed char *data;
-       dma_addr_t data_dma;
-       struct input_dev *dev;
-       struct usb_device *usbdev;
-       struct urb *irq;
-       struct wacom_features *features;
-       int tool[2];
-       int id[2];
-       __u32 serial[2];
-       char phys[32];
-};
-
-#define USB_REQ_GET_REPORT     0x01
-#define USB_REQ_SET_REPORT     0x09
-
-static int usb_get_report(struct usb_interface *intf, unsigned char type,
-                               unsigned char id, void *buf, int size)
-{
-       return usb_control_msg(interface_to_usbdev(intf),
-               usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
-               USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-               (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
-               buf, size, 100);
-}
-
-static int usb_set_report(struct usb_interface *intf, unsigned char type,
-                               unsigned char id, void *buf, int size)
-{
-       return usb_control_msg(interface_to_usbdev(intf),
-               usb_sndctrlpipe(interface_to_usbdev(intf), 0),
-                USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
-               buf, size, 1000);
-}
-
-static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       int prox, pressure, id;
-       int retval;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       if (data[0] != 2) {
-               dbg("wacom_pl_irq: received unknown report #%d", data[0]);
-               goto exit;
-       }
-
-       prox = data[1] & 0x40;
-
-       input_regs(dev, regs);
-
-       id = ERASER_DEVICE_ID;
-       if (prox) {
-
-               pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
-               if (wacom->features->pressure_max > 255)
-                       pressure = (pressure << 1) | ((data[4] >> 6) & 1);
-               pressure += (wacom->features->pressure_max + 1) / 2;
-
-               /*
-                * if going from out of proximity into proximity select between the eraser
-                * and the pen based on the state of the stylus2 button, choose eraser if
-                * pressed else choose pen. if not a proximity change from out to in, send
-                * an out of proximity for previous tool then a in for new tool.
-                */
-               if (!wacom->tool[0]) {
-                       /* Eraser bit set for DTF */
-                       if (data[1] & 0x10)
-                               wacom->tool[1] = BTN_TOOL_RUBBER;
-                       else
-                               /* Going into proximity select tool */
-                               wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-               } else {
-                       /* was entered with stylus2 pressed */
-                       if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
-                               /* report out proximity for previous tool */
-                               input_report_key(dev, wacom->tool[1], 0);
-                               input_sync(dev);
-                               wacom->tool[1] = BTN_TOOL_PEN;
-                               goto exit;
-                       }
-               }
-               if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-                       /* Unknown tool selected default to pen tool */
-                       wacom->tool[1] = BTN_TOOL_PEN;
-                       id = STYLUS_DEVICE_ID;
-               }
-               input_report_key(dev, wacom->tool[1], prox); /* report in proximity for tool */
-               input_report_abs(dev, ABS_MISC, id); /* report tool id */
-               input_report_abs(dev, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
-               input_report_abs(dev, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
-               input_report_abs(dev, ABS_PRESSURE, pressure);
-
-               input_report_key(dev, BTN_TOUCH, data[4] & 0x08);
-               input_report_key(dev, BTN_STYLUS, data[4] & 0x10);
-               /* Only allow the stylus2 button to be reported for the pen tool. */
-               input_report_key(dev, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
-       } else {
-               /* report proximity-out of a (valid) tool */
-               if (wacom->tool[1] != BTN_TOOL_RUBBER) {
-                       /* Unknown tool selected default to pen tool */
-                       wacom->tool[1] = BTN_TOOL_PEN;
-               }
-               input_report_key(dev, wacom->tool[1], prox);
-       }
-
-       wacom->tool[0] = prox; /* Save proximity state */
-       input_sync(dev);
-
- exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
-}
-
-static void wacom_ptu_irq(struct urb *urb, struct pt_regs *regs)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       int retval, id;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       if (data[0] != 2) {
-               printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
-               goto exit;
-       }
-
-       input_regs(dev, regs);
-       if (data[1] & 0x04) {
-               input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x20);
-               input_report_key(dev, BTN_TOUCH, data[1] & 0x08);
-               id = ERASER_DEVICE_ID;
-       } else {
-               input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20);
-               input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
-               id = STYLUS_DEVICE_ID;
-       }
-       input_report_abs(dev, ABS_MISC, id); /* report tool id */
-       input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2]));
-       input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4]));
-       input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
-       input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
-       input_report_key(dev, BTN_STYLUS2, data[1] & 0x10);
-
-       input_sync(dev);
-
- exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
-}
-
-static void wacom_penpartner_irq(struct urb *urb, struct pt_regs *regs)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       int retval;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       if (data[0] != 2) {
-               printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]);
-               goto exit;
-       }
-
-       input_regs(dev, regs);
-       input_report_key(dev, BTN_TOOL_PEN, 1);
-       input_report_abs(dev, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
-       input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1]));
-       input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3]));
-       input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127);
-       input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
-       input_report_key(dev, BTN_STYLUS, (data[5] & 0x40));
-       input_sync(dev);
-
- exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
-}
-
-static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       int x, y, id, rw;
-       int retval;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       if (data[0] == 99) return; /* for Volito tablets */
-
-       if (data[0] != 2) {
-               dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
-               goto exit;
-       }
-
-       input_regs(dev, regs);
-
-       id = STYLUS_DEVICE_ID;
-       if (data[1] & 0x10) { /* in prox */
-
-               switch ((data[1] >> 5) & 3) {
-
-                       case 0: /* Pen */
-                               wacom->tool[0] = BTN_TOOL_PEN;
-                               break;
-
-                       case 1: /* Rubber */
-                               wacom->tool[0] = BTN_TOOL_RUBBER;
-                               id = ERASER_DEVICE_ID;
-                               break;
-
-                       case 2: /* Mouse with wheel */
-                               input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
-                               if (wacom->features->type == WACOM_G4) {
-                                       rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
-                                       input_report_rel(dev, REL_WHEEL, -rw);
-                               } else
-                                       input_report_rel(dev, REL_WHEEL, -(signed char) data[6]);
-                               /* fall through */
-
-                       case 3: /* Mouse without wheel */
-                               wacom->tool[0] = BTN_TOOL_MOUSE;
-                               id = CURSOR_DEVICE_ID;
-                               input_report_key(dev, BTN_LEFT, data[1] & 0x01);
-                               input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
-                               if (wacom->features->type == WACOM_G4)
-                                       input_report_abs(dev, ABS_DISTANCE, data[6]);
-                               else
-                                       input_report_abs(dev, ABS_DISTANCE, data[7]);
-                               break;
-               }
-       }
-
-       if (data[1] & 0x90) {
-               x = le16_to_cpu(*(__le16 *) &data[2]);
-               y = le16_to_cpu(*(__le16 *) &data[4]);
-               input_report_abs(dev, ABS_X, x);
-               input_report_abs(dev, ABS_Y, y);
-               if (wacom->tool[0] != BTN_TOOL_MOUSE) {
-                       input_report_abs(dev, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8));
-                       input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
-                       input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
-                       input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
-               }
-       }
-
-       if (data[1] & 0x10)
-               input_report_abs(dev, ABS_MISC, id); /* report tool id */
-       else
-               input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
-       input_report_key(dev, wacom->tool[0], data[1] & 0x10);
-       input_sync(dev);
-
-       /* send pad data */
-       if (wacom->features->type == WACOM_G4) {
-               if ((wacom->serial[1] & 0xc0) != (data[7] & 0xf8)) {
-                       wacom->id[1] = 1;
-                       wacom->serial[1] = (data[7] & 0xf8);
-                       input_report_key(dev, BTN_0, (data[7] & 0x40));
-                       input_report_key(dev, BTN_4, (data[7] & 0x80));
-                       rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
-                       input_report_rel(dev, REL_WHEEL, rw);
-                       input_report_key(dev, BTN_TOOL_FINGER, 0xf0);
-                       input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
-               } else if (wacom->id[1]) {
-                       wacom->id[1] = 0;
-                       input_report_key(dev, BTN_TOOL_FINGER, 0);
-                       input_event(dev, EV_MSC, MSC_SERIAL, 0xf0);
-               }
-               input_sync(dev);
-       }
- exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               err ("%s - usb_submit_urb failed with result %d",
-                    __FUNCTION__, retval);
-}
-
-static int wacom_intuos_inout(struct urb *urb)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       int idx;
-
-       /* tool number */
-       idx = data[1] & 0x01;
-
-       /* Enter report */
-       if ((data[1] & 0xfc) == 0xc0) {
-               /* serial number of the tool */
-               wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
-                       (data[4] << 20) + (data[5] << 12) +
-                       (data[6] << 4) + (data[7] >> 4);
-
-               wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);
-               switch (wacom->id[idx]) {
-                       case 0x812: /* Inking pen */
-                       case 0x801: /* Intuos3 Inking pen */
-                       case 0x012:
-                               wacom->tool[idx] = BTN_TOOL_PENCIL;
-                               break;
-                       case 0x822: /* Pen */
-                       case 0x842:
-                       case 0x852:
-                       case 0x823: /* Intuos3 Grip Pen */
-                       case 0x813: /* Intuos3 Classic Pen */
-                       case 0x885: /* Intuos3 Marker Pen */
-                       case 0x022:
-                               wacom->tool[idx] = BTN_TOOL_PEN;
-                               break;
-                       case 0x832: /* Stroke pen */
-                       case 0x032:
-                               wacom->tool[idx] = BTN_TOOL_BRUSH;
-                               break;
-                       case 0x007: /* Mouse 4D and 2D */
-                       case 0x09c:
-                       case 0x094:
-                       case 0x017: /* Intuos3 2D Mouse */
-                               wacom->tool[idx] = BTN_TOOL_MOUSE;
-                               break;
-                       case 0x096: /* Lens cursor */
-                       case 0x097: /* Intuos3 Lens cursor */
-                               wacom->tool[idx] = BTN_TOOL_LENS;
-                               break;
-                       case 0x82a: /* Eraser */
-                       case 0x85a:
-                       case 0x91a:
-                       case 0xd1a:
-                       case 0x0fa:
-                       case 0x82b: /* Intuos3 Grip Pen Eraser */
-                       case 0x81b: /* Intuos3 Classic Pen Eraser */
-                       case 0x91b: /* Intuos3 Airbrush Eraser */
-                               wacom->tool[idx] = BTN_TOOL_RUBBER;
-                               break;
-                       case 0xd12:
-                       case 0x912:
-                       case 0x112:
-                       case 0x913: /* Intuos3 Airbrush */
-                               wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
-                               break;
-                       default: /* Unknown tool */
-                               wacom->tool[idx] = BTN_TOOL_PEN;
-               }
-               if(!((wacom->tool[idx] == BTN_TOOL_LENS) &&
-                               ((wacom->features->type == INTUOS312)
-                                       || (wacom->features->type == INTUOS319)))) {
-                       input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
-                       input_report_key(dev, wacom->tool[idx], 1);
-                       input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-                       input_sync(dev);
-               }
-               return 1;
-       }
-
-       /* Exit report */
-       if ((data[1] & 0xfe) == 0x80) {
-               input_report_key(dev, wacom->tool[idx], 0);
-               input_report_abs(dev, ABS_MISC, 0); /* reset tool id */
-               input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-               input_sync(dev);
-               return 1;
-       }
-
-       if((wacom->tool[idx] == BTN_TOOL_LENS) && ((wacom->features->type == INTUOS312)
-                       || (wacom->features->type == INTUOS319)))
-               return 1;
-       else
-               return 0;
-}
-
-static void wacom_intuos_general(struct urb *urb)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       unsigned int t;
-
-       /* general pen packet */
-       if ((data[1] & 0xb8) == 0xa0) {
-               t = (data[6] << 2) | ((data[7] >> 6) & 3);
-               input_report_abs(dev, ABS_PRESSURE, t);
-               input_report_abs(dev, ABS_TILT_X,
-                               ((data[7] << 1) & 0x7e) | (data[8] >> 7));
-               input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
-               input_report_key(dev, BTN_STYLUS, data[1] & 2);
-               input_report_key(dev, BTN_STYLUS2, data[1] & 4);
-               input_report_key(dev, BTN_TOUCH, t > 10);
-       }
-
-       /* airbrush second packet */
-       if ((data[1] & 0xbc) == 0xb4) {
-               input_report_abs(dev, ABS_WHEEL,
-                               (data[6] << 2) | ((data[7] >> 6) & 3));
-               input_report_abs(dev, ABS_TILT_X,
-                               ((data[7] << 1) & 0x7e) | (data[8] >> 7));
-               input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
-       }
-       return;
-}
-
-static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
-{
-       struct wacom *wacom = urb->context;
-       unsigned char *data = wacom->data;
-       struct input_dev *dev = wacom->dev;
-       unsigned int t;
-       int idx;
-       int retval;
-
-       switch (urb->status) {
-       case 0:
-               /* success */
-               break;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-               /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-               return;
-       default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-               goto exit;
-       }
-
-       if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
-               dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
-               goto exit;
-       }
-
-       input_regs(dev, regs);
-
-       /* tool number */
-       idx = data[1] & 0x01;
-
-       /* pad packets. Works as a second tool and is always in prox */
-       if (data[0] == 12) {
-               /* initiate the pad as a device */
-               if (wacom->tool[1] != BTN_TOOL_FINGER)
-                       wacom->tool[1] = BTN_TOOL_FINGER;
-
-               input_report_key(dev, BTN_0, (data[5] & 0x01));
-               input_report_key(dev, BTN_1, (data[5] & 0x02));
-               input_report_key(dev, BTN_2, (data[5] & 0x04));
-               input_report_key(dev, BTN_3, (data[5] & 0x08));
-               input_report_key(dev, BTN_4, (data[6] & 0x01));
-               input_report_key(dev, BTN_5, (data[6] & 0x02));
-               input_report_key(dev, BTN_6, (data[6] & 0x04));
-               input_report_key(dev, BTN_7, (data[6] & 0x08));
-               input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
-               input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
-
-               if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2])
-                       input_report_key(dev, wacom->tool[1], 1);
-               else
-                       input_report_key(dev, wacom->tool[1], 0);
-               input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff);
-               input_sync(dev);
-               goto exit;
-       }
-
-       /* process in/out prox events */
-       if (wacom_intuos_inout(urb))
-               goto exit;
-
-       /* Cintiq doesn't send data when RDY bit isn't set */
-       if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
-               goto exit;
-
-       if (wacom->features->type >= INTUOS3) {
-               input_report_abs(dev, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
-               input_report_abs(dev, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
-               input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
-       } else {
-               input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2]));
-               input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4]));
-               input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
-       }
-
-       /* process general packets */
-       wacom_intuos_general(urb);
-
-       /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */
-       if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {
-
-               if (data[1] & 0x02) {
-                       /* Rotation packet */
-                       if (wacom->features->type >= INTUOS3) {
-                               /* I3 marker pen rotation reported as wheel
-                                * due to valuator limitation
-                                */
-                               t = (data[6] << 3) | ((data[7] >> 5) & 7);
-                               t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
-                                       ((t-1) / 2 + 450)) : (450 - t / 2) ;
-                               input_report_abs(dev, ABS_WHEEL, t);
-                       } else {
-                               /* 4D mouse rotation packet */
-                               t = (data[6] << 3) | ((data[7] >> 5) & 7);
-                               input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
-                                       ((t - 1) / 2) : -t / 2);
-                       }
-
-               } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) {
-                       /* 4D mouse packet */
-                       input_report_key(dev, BTN_LEFT,   data[8] & 0x01);
-                       input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
-                       input_report_key(dev, BTN_RIGHT,  data[8] & 0x04);
-
-                       input_report_key(dev, BTN_SIDE,   data[8] & 0x20);
-                       input_report_key(dev, BTN_EXTRA,  data[8] & 0x10);
-                       t = (data[6] << 2) | ((data[7] >> 6) & 3);
-                       input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
-
-               } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
-                       /* 2D mouse packet */
-                       input_report_key(dev, BTN_LEFT,   data[8] & 0x04);
-                       input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
-                       input_report_key(dev, BTN_RIGHT,  data[8] & 0x10);
-                       input_report_rel(dev, REL_WHEEL, (data[8] & 0x01)
-                                                - ((data[8] & 0x02) >> 1));
-
-                       /* I3 2D mouse side buttons */
-                       if (wacom->features->type == INTUOS3) {
-                               input_report_key(dev, BTN_SIDE,   data[8] & 0x40);
-                               input_report_key(dev, BTN_EXTRA,  data[8] & 0x20);
-                       }
-
-               } else if (wacom->features->type < INTUOS3) {
-                       /* Lens cursor packets */
-                       input_report_key(dev, BTN_LEFT,   data[8] & 0x01);
-                       input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
-                       input_report_key(dev, BTN_RIGHT,  data[8] & 0x04);
-                       input_report_key(dev, BTN_SIDE,   data[8] & 0x10);
-                       input_report_key(dev, BTN_EXTRA,  data[8] & 0x08);
-               }
-       }
-
-       input_report_abs(dev, ABS_MISC, wacom->id[idx]); /* report tool id */
-       input_report_key(dev, wacom->tool[idx], 1);
-       input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
-       input_sync(dev);
-
-exit:
-       retval = usb_submit_urb (urb, GFP_ATOMIC);
-       if (retval)
-               err ("%s - usb_submit_urb failed with result %d",
-                   __FUNCTION__, retval);
-}
-
-static struct wacom_features wacom_features[] = {
-       { "Wacom Penpartner",    7,   5040,  3780,  255, 32, PENPARTNER, wacom_penpartner_irq },
-        { "Wacom Graphire",      8,  10206,  7422,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Graphire3",     8,  10208,  7424,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 32, WACOM_G4,   wacom_graphire_irq },
-       { "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 32, WACOM_G4,   wacom_graphire_irq },
-       { "Wacom Volito",        8,   5104,  3712,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom PenStation2",   8,   3250,  2320,  255, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Volito2 4x5",   8,   5104,  3712,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Volito2 2x3",   8,   3248,  2320,  511, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom PenPartner2",   8,   3250,  2320,  255, 32, GRAPHIRE,   wacom_graphire_irq },
-       { "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom PL400",         8,   5408,  4056,  255, 32, PL,         wacom_pl_irq },
-       { "Wacom PL500",         8,   6144,  4608,  255, 32, PL,         wacom_pl_irq },
-       { "Wacom PL600",         8,   6126,  4604,  255, 32, PL,         wacom_pl_irq },
-       { "Wacom PL600SX",       8,   6260,  5016,  255, 32, PL,         wacom_pl_irq },
-       { "Wacom PL550",         8,   6144,  4608,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom PL800",         8,   7220,  5780,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom PL700",         8,   6758,  5406,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom PL510",         8,   6282,  4762,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom DTU710",        8,  34080, 27660,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom DTF521",        8,   6282,  4762,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom DTF720",        8,   6858,  5506,  511, 32, PL,         wacom_pl_irq },
-       { "Wacom Cintiq Partner",8,  20480, 15360,  511, 32, PL,         wacom_ptu_irq },
-       { "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 15, INTUOS3,    wacom_intuos_irq },
-       { "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 15, INTUOS3,    wacom_intuos_irq },
-       { "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 15, INTUOS3,    wacom_intuos_irq },
-       { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS312,  wacom_intuos_irq },
-       { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS319,  wacom_intuos_irq },
-       { "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 15, INTUOS3,    wacom_intuos_irq },
-       { "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 15, CINTIQ,     wacom_intuos_irq },
-       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,     wacom_intuos_irq },
-       { }
-};
-
-static struct usb_device_id wacom_ids[] = {
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC3) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
-       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
-       { }
-};
-
-MODULE_DEVICE_TABLE(usb, wacom_ids);
-
-static int wacom_open(struct input_dev *dev)
-{
-       struct wacom *wacom = dev->private;
-
-       wacom->irq->dev = wacom->usbdev;
-       if (usb_submit_urb(wacom->irq, GFP_KERNEL))
-               return -EIO;
-
-       return 0;
-}
-
-static void wacom_close(struct input_dev *dev)
-{
-       struct wacom *wacom = dev->private;
-
-       usb_kill_urb(wacom->irq);
-}
-
-static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-       struct usb_device *dev = interface_to_usbdev(intf);
-       struct usb_endpoint_descriptor *endpoint;
-       struct wacom *wacom;
-       struct input_dev *input_dev;
-       char rep_data[2], limit = 0;
-
-       wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!wacom || !input_dev)
-               goto fail1;
-
-       wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
-       if (!wacom->data)
-               goto fail1;
-
-       wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
-       if (!wacom->irq)
-               goto fail2;
-
-       wacom->usbdev = dev;
-       wacom->dev = input_dev;
-       usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
-       strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
-
-       wacom->features = wacom_features + (id - wacom_ids);
-       if (wacom->features->pktlen > 10)
-               BUG();
-
-       input_dev->name = wacom->features->name;
-       usb_to_input_id(dev, &input_dev->id);
-
-       input_dev->cdev.dev = &intf->dev;
-       input_dev->private = wacom;
-       input_dev->open = wacom_open;
-       input_dev->close = wacom_close;
-
-       input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
-       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
-       input_set_abs_params(input_dev, ABS_X, 0, wacom->features->x_max, 4, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, wacom->features->y_max, 4, 0);
-       input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0);
-       input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC);
-
-       switch (wacom->features->type) {
-               case WACOM_G4:
-                       input_dev->evbit[0] |= BIT(EV_MSC);
-                       input_dev->mscbit[0] |= BIT(MSC_SERIAL);
-                       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
-                       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
-                       /* fall through */
-
-               case GRAPHIRE:
-                       input_dev->evbit[0] |= BIT(EV_REL);
-                       input_dev->relbit[0] |= BIT(REL_WHEEL);
-                       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-                       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
-                       input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
-                       break;
-
-               case INTUOS3:
-               case INTUOS312:
-               case INTUOS319:
-               case CINTIQ:
-                       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
-                       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
-                       input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
-                       input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
-                       /* fall through */
-
-               case INTUOS:
-                       input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
-                       input_dev->mscbit[0] |= BIT(MSC_SERIAL);
-                       input_dev->relbit[0] |= BIT(REL_WHEEL);
-                       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
-                       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH)
-                                                         | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2);
-                       input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom->features->distance_max, 0, 0);
-                       input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
-                       input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
-                       input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
-                       input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
-                       input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
-                       break;
-
-               case PL:
-                       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
-                       break;
-       }
-
-       endpoint = &intf->cur_altsetting->endpoint[0].desc;
-
-       if (wacom->features->pktlen > 10)
-               BUG();
-
-       usb_fill_int_urb(wacom->irq, dev,
-                        usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-                        wacom->data, wacom->features->pktlen,
-                        wacom->features->irq, wacom, endpoint->bInterval);
-       wacom->irq->transfer_dma = wacom->data_dma;
-       wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
-       input_register_device(wacom->dev);
-
-       /* Ask the tablet to report tablet data. Repeat until it succeeds */
-       do {
-               rep_data[0] = 2;
-               rep_data[1] = 2;
-               usb_set_report(intf, 3, 2, rep_data, 2);
-               usb_get_report(intf, 3, 2, rep_data, 2);
-       } while (rep_data[1] != 2 && limit++ < 5);
-
-       usb_set_intfdata(intf, wacom);
-       return 0;
-
-fail2: usb_buffer_free(dev, 10, wacom->data, wacom->data_dma);
-fail1: input_free_device(input_dev);
-       kfree(wacom);
-       return -ENOMEM;
-}
-
-static void wacom_disconnect(struct usb_interface *intf)
-{
-       struct wacom *wacom = usb_get_intfdata (intf);
-
-       usb_set_intfdata(intf, NULL);
-       if (wacom) {
-               usb_kill_urb(wacom->irq);
-               input_unregister_device(wacom->dev);
-               usb_free_urb(wacom->irq);
-               usb_buffer_free(interface_to_usbdev(intf), 10, wacom->data, wacom->data_dma);
-               kfree(wacom);
-       }
-}
-
-static struct usb_driver wacom_driver = {
-       .name =         "wacom",
-       .probe =        wacom_probe,
-       .disconnect =   wacom_disconnect,
-       .id_table =     wacom_ids,
-};
-
-static int __init wacom_init(void)
-{
-       int result = usb_register(&wacom_driver);
-       if (result == 0)
-               info(DRIVER_VERSION ":" DRIVER_DESC);
-       return result;
-}
-
-static void __exit wacom_exit(void)
-{
-       usb_deregister(&wacom_driver);
-}
-
-module_init(wacom_init);
-module_exit(wacom_exit);
diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h
new file mode 100644 (file)
index 0000000..832737b
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * drivers/usb/input/wacom.h
+ *
+ *  USB Wacom Graphire and Wacom Intuos tablet support
+ *
+ *  Copyright (c) 2000-2004 Vojtech Pavlik     <vojtech@ucw.cz>
+ *  Copyright (c) 2000 Andreas Bach Aaen       <abach@stofanet.dk>
+ *  Copyright (c) 2000 Clifford Wolf           <clifford@clifford.at>
+ *  Copyright (c) 2000 Sam Mosel               <sam.mosel@computer.org>
+ *  Copyright (c) 2000 James E. Blair          <corvus@gnu.org>
+ *  Copyright (c) 2000 Daniel Egger            <egger@suse.de>
+ *  Copyright (c) 2001 Frederic Lepied         <flepied@mandrakesoft.com>
+ *  Copyright (c) 2004 Panagiotis Issaris      <panagiotis.issaris@mech.kuleuven.ac.be>
+ *  Copyright (c) 2002-2006 Ping Cheng         <pingc@wacom.com>
+ *
+ *  ChangeLog:
+ *      v0.1 (vp)  - Initial release
+ *      v0.2 (aba) - Support for all buttons / combinations
+ *      v0.3 (vp)  - Support for Intuos added
+ *     v0.4 (sm)  - Support for more Intuos models, menustrip
+ *                     relative mode, proximity.
+ *     v0.5 (vp)  - Big cleanup, nifty features removed,
+ *                     they belong in userspace
+ *     v1.8 (vp)  - Submit URB only when operating, moved to CVS,
+ *                     use input_report_key instead of report_btn and
+ *                     other cleanups
+ *     v1.11 (vp) - Add URB ->dev setting for new kernels
+ *     v1.11 (jb) - Add support for the 4D Mouse & Lens
+ *     v1.12 (de) - Add support for two more inking pen IDs
+ *     v1.14 (vp) - Use new USB device id probing scheme.
+ *                  Fix Wacom Graphire mouse wheel
+ *     v1.18 (vp) - Fix mouse wheel direction
+ *                  Make mouse relative
+ *      v1.20 (fl) - Report tool id for Intuos devices
+ *                 - Multi tools support
+ *                 - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
+ *                 - Add PL models support
+ *                - Fix Wacom Graphire mouse wheel again
+ *     v1.21 (vp) - Removed protocol descriptions
+ *                - Added MISC_SERIAL for tool serial numbers
+ *           (gb) - Identify version on module load.
+ *    v1.21.1 (fl) - added Graphire2 support
+ *    v1.21.2 (fl) - added Intuos2 support
+ *                 - added all the PL ids
+ *    v1.21.3 (fl) - added another eraser id from Neil Okamoto
+ *                 - added smooth filter for Graphire from Peri Hankey
+ *                 - added PenPartner support from Olaf van Es
+ *                 - new tool ids from Ole Martin Bjoerndalen
+ *     v1.29 (pc) - Add support for more tablets
+ *                - Fix pressure reporting
+ *     v1.30 (vp) - Merge 2.4 and 2.5 drivers
+ *                - Since 2.5 now has input_sync(), remove MSC_SERIAL abuse
+ *                - Cleanups here and there
+ *    v1.30.1 (pi) - Added Graphire3 support
+ *     v1.40 (pc) - Add support for several new devices, fix eraser reporting, ...
+ *     v1.43 (pc) - Added support for Cintiq 21UX
+ *                - Fixed a Graphire bug
+ *                - Merged wacom_intuos3_irq into wacom_intuos_irq
+ *     v1.44 (pc) - Added support for Graphire4, Cintiq 710, Intuos3 6x11, etc.
+ *                - Report Device IDs
+ *      v1.45 (pc) - Added support for DTF 521, Intuos3 12x12 and 12x19
+ *                 - Minor data report fix
+ *      v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c,
+ *                - where wacom_sys.c deals with system specific code,
+ *                - and wacom_wac.c deals with Wacom specific code
+ */
+
+/*
+ * 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 WACOM_H
+#define WACOM_H
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb/input.h>
+#include <asm/unaligned.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.46"
+#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
+#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
+#define DRIVER_LICENSE "GPL"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+#define USB_VENDOR_ID_WACOM    0x056a
+
+struct wacom {
+       dma_addr_t data_dma;
+       struct input_dev *dev;
+       struct usb_device *usbdev;
+       struct urb *irq;
+       struct wacom_wac * wacom_wac;
+       char phys[32];
+};
+
+struct wacom_combo {
+       struct wacom * wacom;
+       struct urb * urb;
+       struct pt_regs *regs;
+};
+
+extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
+extern void wacom_sys_irq(struct urb *urb, struct pt_regs *regs);
+extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data);
+extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data);
+extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data);
+extern void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value);
+extern void wacom_input_regs(void *wcombo);
+extern void wacom_input_sync(void *wcombo);
+extern void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac);
+extern __u16 wacom_le16_to_cpu(unsigned char *data);
+extern __u16 wacom_be16_to_cpu(unsigned char *data);
+extern struct wacom_features * get_wacom_feature(const struct usb_device_id *id);
+extern const struct usb_device_id * get_device_table(void);
+
+#endif
diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c
new file mode 100644 (file)
index 0000000..7c3b52b
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * drivers/usb/input/wacom_sys.c
+ *
+ *  USB Wacom Graphire and Wacom Intuos tablet support - system specific code
+ */
+
+/*
+ * 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 "wacom.h"
+#include "wacom_wac.h"
+
+#define USB_REQ_GET_REPORT     0x01
+#define USB_REQ_SET_REPORT     0x09
+
+static int usb_get_report(struct usb_interface *intf, unsigned char type,
+                               unsigned char id, void *buf, int size)
+{
+       return usb_control_msg(interface_to_usbdev(intf),
+               usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
+               USB_REQ_GET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+               (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
+               buf, size, 100);
+}
+
+static int usb_set_report(struct usb_interface *intf, unsigned char type,
+                               unsigned char id, void *buf, int size)
+{
+       return usb_control_msg(interface_to_usbdev(intf),
+               usb_sndctrlpipe(interface_to_usbdev(intf), 0),
+                USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
+               buf, size, 1000);
+}
+
+static struct input_dev * get_input_dev(struct wacom_combo *wcombo)
+{
+       return wcombo->wacom->dev;
+}
+
+void wacom_sys_irq(struct urb *urb, struct pt_regs *regs)
+{
+       struct wacom *wacom = urb->context;
+       struct wacom_combo wcombo;
+       int retval;
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               return;
+       default:
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               goto exit;
+       }
+
+       wcombo.wacom = wacom;
+       wcombo.urb = urb;
+       wcombo.regs = regs;
+
+       if (wacom_wac_irq(wacom->wacom_wac, (void *)&wcombo))
+               input_sync(get_input_dev(&wcombo));
+
+ exit:
+       retval = usb_submit_urb (urb, GFP_ATOMIC);
+       if (retval)
+               err ("%s - usb_submit_urb failed with result %d",
+                    __FUNCTION__, retval);
+}
+
+void wacom_report_key(void *wcombo, unsigned int key_type, int key_data)
+{
+       input_report_key(get_input_dev((struct wacom_combo *)wcombo), key_type, key_data);
+       return;
+}
+
+void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data)
+{
+       input_report_abs(get_input_dev((struct wacom_combo *)wcombo), abs_type, abs_data);
+       return;
+}
+
+void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data)
+{
+       input_report_rel(get_input_dev((struct wacom_combo *)wcombo), rel_type, rel_data);
+       return;
+}
+
+void wacom_input_event(void *wcombo, unsigned int type, unsigned int code, int value)
+{
+       input_event(get_input_dev((struct wacom_combo *)wcombo), type, code, value);
+       return;
+}
+
+__u16 wacom_be16_to_cpu(unsigned char *data)
+{
+       __u16 value;
+       value = be16_to_cpu(*(__be16 *) data);
+       return value;
+}
+
+__u16 wacom_le16_to_cpu(unsigned char *data)
+{
+       __u16 value;
+       value = be16_to_cpu(*(__be16 *) data);
+       return value;
+}
+
+void wacom_input_regs(void *wcombo)
+{
+       input_regs(get_input_dev((struct wacom_combo *)wcombo), ((struct wacom_combo *)wcombo)->regs);
+       return;
+}
+
+void wacom_input_sync(void *wcombo)
+{
+       input_sync(get_input_dev((struct wacom_combo *)wcombo));
+       return;
+}
+
+static int wacom_open(struct input_dev *dev)
+{
+       struct wacom *wacom = dev->private;
+
+       wacom->irq->dev = wacom->usbdev;
+       if (usb_submit_urb(wacom->irq, GFP_KERNEL))
+               return -EIO;
+
+       return 0;
+}
+
+static void wacom_close(struct input_dev *dev)
+{
+       struct wacom *wacom = dev->private;
+
+       usb_kill_urb(wacom->irq);
+}
+
+void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->evbit[0] |= BIT(EV_MSC);
+       input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
+       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+}
+
+void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->evbit[0] |= BIT(EV_REL);
+       input_dev->relbit[0] |= BIT(REL_WHEEL);
+       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
+       input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
+}
+
+void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
+       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+       input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0);
+       input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0);
+}
+
+void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
+       input_dev->mscbit[0] |= BIT(MSC_SERIAL);
+       input_dev->relbit[0] |= BIT(REL_WHEEL);
+       input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA);
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH)
+               | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2);
+       input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0);
+       input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
+       input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
+       input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
+       input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
+       input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
+}
+
+void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
+}
+
+void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER);
+}
+
+static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       struct usb_device *dev = interface_to_usbdev(intf);
+       struct usb_endpoint_descriptor *endpoint;
+       struct wacom *wacom;
+       struct wacom_wac *wacom_wac;
+       struct input_dev *input_dev;
+       char rep_data[2], limit = 0;
+
+       wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL);
+       wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!wacom || !input_dev || !wacom_wac)
+               goto fail1;
+
+       wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma);
+       if (!wacom_wac->data)
+               goto fail1;
+
+       wacom->irq = usb_alloc_urb(0, GFP_KERNEL);
+       if (!wacom->irq)
+               goto fail2;
+
+       wacom->usbdev = dev;
+       wacom->dev = input_dev;
+       usb_make_path(dev, wacom->phys, sizeof(wacom->phys));
+       strlcat(wacom->phys, "/input0", sizeof(wacom->phys));
+
+       wacom_wac->features = get_wacom_feature(id);
+       if (wacom_wac->features->pktlen > 10)
+               BUG();
+
+       input_dev->name = wacom_wac->features->name;
+       wacom->wacom_wac = wacom_wac;
+       usb_to_input_id(dev, &input_dev->id);
+
+       input_dev->cdev.dev = &intf->dev;
+       input_dev->private = wacom;
+       input_dev->open = wacom_open;
+       input_dev->close = wacom_close;
+
+       input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
+       input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
+       input_set_abs_params(input_dev, ABS_X, 0, wacom_wac->features->x_max, 4, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, wacom_wac->features->y_max, 4, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom_wac->features->pressure_max, 0, 0);
+       input_dev->absbit[LONG(ABS_MISC)] |= BIT(ABS_MISC);
+
+       wacom_init_input_dev(input_dev, wacom_wac);
+
+       endpoint = &intf->cur_altsetting->endpoint[0].desc;
+
+       usb_fill_int_urb(wacom->irq, dev,
+                        usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+                        wacom_wac->data, wacom_wac->features->pktlen,
+                        wacom_wac->features->irq, wacom, endpoint->bInterval);
+       wacom->irq->transfer_dma = wacom->data_dma;
+       wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       input_register_device(wacom->dev);
+
+       /* Ask the tablet to report tablet data. Repeat until it succeeds */
+       do {
+               rep_data[0] = 2;
+               rep_data[1] = 2;
+               usb_set_report(intf, 3, 2, rep_data, 2);
+               usb_get_report(intf, 3, 2, rep_data, 2);
+       } while (rep_data[1] != 2 && limit++ < 5);
+
+       usb_set_intfdata(intf, wacom);
+       return 0;
+
+fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma);
+fail1: input_free_device(input_dev);
+       kfree(wacom);
+       kfree(wacom_wac);
+       return -ENOMEM;
+}
+
+static void wacom_disconnect(struct usb_interface *intf)
+{
+       struct wacom *wacom = usb_get_intfdata (intf);
+
+       usb_set_intfdata(intf, NULL);
+       if (wacom) {
+               usb_kill_urb(wacom->irq);
+               input_unregister_device(wacom->dev);
+               usb_free_urb(wacom->irq);
+               usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma);
+               kfree(wacom);
+               kfree(wacom->wacom_wac);
+       }
+}
+
+static struct usb_driver wacom_driver = {
+       .name =         "wacom",
+       .probe =        wacom_probe,
+       .disconnect =   wacom_disconnect,
+};
+
+static int __init wacom_init(void)
+{
+       int result;
+       wacom_driver.id_table = get_device_table();
+       result = usb_register(&wacom_driver);
+       if (result == 0)
+               info(DRIVER_VERSION ":" DRIVER_DESC);
+       return result;
+}
+
+static void __exit wacom_exit(void)
+{
+       usb_deregister(&wacom_driver);
+}
+
+module_init(wacom_init);
+module_exit(wacom_exit);
diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c
new file mode 100644 (file)
index 0000000..85d458c
--- /dev/null
@@ -0,0 +1,646 @@
+/*
+ * drivers/usb/input/wacom_wac.c
+ *
+ *  USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code
+ *
+ */
+
+/*
+ * 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 "wacom.h"
+#include "wacom_wac.h"
+
+static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+
+       switch (data[0]) {
+               case 1:
+                       wacom_input_regs(wcombo);
+                       if (data[5] & 0x80) {
+                               wacom->tool[0] = (data[5] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+                               wacom->id[0] = (data[5] & 0x20) ? ERASER_DEVICE_ID : STYLUS_DEVICE_ID;
+                               wacom_report_key(wcombo, wacom->tool[0], 1);
+                               wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */
+                               wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
+                               wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
+                               wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127);
+                               wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -127));
+                               wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40));
+                       } else {
+                               wacom_report_key(wcombo, wacom->tool[0], 0);
+                               wacom_report_abs(wcombo, ABS_MISC, 0); /* report tool id */
+                               wacom_report_abs(wcombo, ABS_PRESSURE, -1);
+                               wacom_report_key(wcombo, BTN_TOUCH, 0);
+                       }
+                       break;
+               case 2:
+                       wacom_input_regs(wcombo);
+                       wacom_report_key(wcombo, BTN_TOOL_PEN, 1);
+                       wacom_report_abs(wcombo, ABS_MISC, STYLUS_DEVICE_ID); /* report tool id */
+                       wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1]));
+                       wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3]));
+                       wacom_report_abs(wcombo, ABS_PRESSURE, (signed char)data[6] + 127);
+                       wacom_report_key(wcombo, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
+                       wacom_report_key(wcombo, BTN_STYLUS, (data[5] & 0x40));
+                       break;
+               default:
+                       printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]);
+                       return 0;
+        }
+       return 1;
+}
+
+static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       int prox, id, pressure;
+
+       if (data[0] != 2) {
+               dbg("wacom_pl_irq: received unknown report #%d", data[0]);
+               return 0;
+       }
+
+       prox = data[1] & 0x40;
+
+       wacom_input_regs(wcombo);
+
+       id = ERASER_DEVICE_ID;
+       if (prox) {
+
+               pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1));
+               if (wacom->features->pressure_max > 255)
+                       pressure = (pressure << 1) | ((data[4] >> 6) & 1);
+               pressure += (wacom->features->pressure_max + 1) / 2;
+
+               /*
+                * if going from out of proximity into proximity select between the eraser
+                * and the pen based on the state of the stylus2 button, choose eraser if
+                * pressed else choose pen. if not a proximity change from out to in, send
+                * an out of proximity for previous tool then a in for new tool.
+                */
+               if (!wacom->tool[0]) {
+                       /* Eraser bit set for DTF */
+                       if (data[1] & 0x10)
+                               wacom->tool[1] = BTN_TOOL_RUBBER;
+                       else
+                               /* Going into proximity select tool */
+                               wacom->tool[1] = (data[4] & 0x20) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+               } else {
+                       /* was entered with stylus2 pressed */
+                       if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[4] & 0x20)) {
+                               /* report out proximity for previous tool */
+                               wacom_report_key(wcombo, wacom->tool[1], 0);
+                               wacom_input_sync(wcombo);
+                               wacom->tool[1] = BTN_TOOL_PEN;
+                               return 0;
+                       }
+               }
+               if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+                       /* Unknown tool selected default to pen tool */
+                       wacom->tool[1] = BTN_TOOL_PEN;
+                       id = STYLUS_DEVICE_ID;
+               }
+               wacom_report_key(wcombo, wacom->tool[1], prox); /* report in proximity for tool */
+               wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+               wacom_report_abs(wcombo, ABS_X, data[3] | (data[2] << 7) | ((data[1] & 0x03) << 14));
+               wacom_report_abs(wcombo, ABS_Y, data[6] | (data[5] << 7) | ((data[4] & 0x03) << 14));
+               wacom_report_abs(wcombo, ABS_PRESSURE, pressure);
+
+               wacom_report_key(wcombo, BTN_TOUCH, data[4] & 0x08);
+               wacom_report_key(wcombo, BTN_STYLUS, data[4] & 0x10);
+               /* Only allow the stylus2 button to be reported for the pen tool. */
+               wacom_report_key(wcombo, BTN_STYLUS2, (wacom->tool[1] == BTN_TOOL_PEN) && (data[4] & 0x20));
+       } else {
+               /* report proximity-out of a (valid) tool */
+               if (wacom->tool[1] != BTN_TOOL_RUBBER) {
+                       /* Unknown tool selected default to pen tool */
+                       wacom->tool[1] = BTN_TOOL_PEN;
+               }
+               wacom_report_key(wcombo, wacom->tool[1], prox);
+       }
+
+       wacom->tool[0] = prox; /* Save proximity state */
+       return 1;
+}
+
+static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       int id;
+
+       if (data[0] != 2) {
+               printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
+               return 0;
+       }
+
+       wacom_input_regs(wcombo);
+       if (data[1] & 0x04) {
+               wacom_report_key(wcombo, BTN_TOOL_RUBBER, data[1] & 0x20);
+               wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x08);
+               id = ERASER_DEVICE_ID;
+       } else {
+               wacom_report_key(wcombo, BTN_TOOL_PEN, data[1] & 0x20);
+               wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);
+               id = STYLUS_DEVICE_ID;
+       }
+       wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+       wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2]));
+       wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4]));
+       wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6]));
+       wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
+       wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
+       return 1;
+}
+
+static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       int x, y, id, rw;
+
+       if (data[0] != 2) {
+               dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
+               return 0;
+       }
+
+       wacom_input_regs(wcombo);
+
+       id = STYLUS_DEVICE_ID;
+       if (data[1] & 0x10) { /* in prox */
+
+               switch ((data[1] >> 5) & 3) {
+
+                       case 0: /* Pen */
+                               wacom->tool[0] = BTN_TOOL_PEN;
+                               break;
+
+                       case 1: /* Rubber */
+                               wacom->tool[0] = BTN_TOOL_RUBBER;
+                               id = ERASER_DEVICE_ID;
+                               break;
+
+                       case 2: /* Mouse with wheel */
+                               wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04);
+                               if (wacom->features->type == WACOM_G4) {
+                                       rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03);
+                                       wacom_report_rel(wcombo, REL_WHEEL, -rw);
+                               } else
+                                       wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]);
+                               /* fall through */
+
+                       case 3: /* Mouse without wheel */
+                               wacom->tool[0] = BTN_TOOL_MOUSE;
+                               id = CURSOR_DEVICE_ID;
+                               wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01);
+                               wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02);
+                               if (wacom->features->type == WACOM_G4)
+                                       wacom_report_abs(wcombo, ABS_DISTANCE, data[6]);
+                               else
+                                       wacom_report_abs(wcombo, ABS_DISTANCE, data[7]);
+                               break;
+               }
+       }
+
+       if (data[1] & 0x90) {
+               x = wacom_le16_to_cpu(&data[2]);
+               y = wacom_le16_to_cpu(&data[4]);
+               wacom_report_abs(wcombo, ABS_X, x);
+               wacom_report_abs(wcombo, ABS_Y, y);
+               if (wacom->tool[0] != BTN_TOOL_MOUSE) {
+                       wacom_report_abs(wcombo, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8));
+                       wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01);
+                       wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
+                       wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04);
+               }
+       }
+
+       if (data[1] & 0x10)
+               wacom_report_abs(wcombo, ABS_MISC, id); /* report tool id */
+       else
+               wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
+       wacom_report_key(wcombo, wacom->tool[0], data[1] & 0x10);
+       wacom_input_sync(wcombo);
+
+       /* send pad data */
+       if (wacom->features->type == WACOM_G4) {
+               if ( (wacom->serial[1] & 0xc0) != (data[7] & 0xf8) ) {
+                       wacom->id[1] = 1;
+                       wacom->serial[1] = (data[7] & 0xf8);
+                       wacom_report_key(wcombo, BTN_0, (data[7] & 0x40));
+                       wacom_report_key(wcombo, BTN_4, (data[7] & 0x80));
+                       rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3);
+                       wacom_report_rel(wcombo, REL_WHEEL, rw);
+                       wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0);
+                       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+               } else if (wacom->id[1]) {
+                       wacom->id[1] = 0;
+                       wacom_report_key(wcombo, BTN_TOOL_FINGER, 0);
+                       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0);
+               }
+       }
+       return 1;
+}
+
+static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       int idx;
+
+       /* tool number */
+       idx = data[1] & 0x01;
+
+       /* Enter report */
+       if ((data[1] & 0xfc) == 0xc0) {
+               /* serial number of the tool */
+               wacom->serial[idx] = ((data[3] & 0x0f) << 28) +
+                       (data[4] << 20) + (data[5] << 12) +
+                       (data[6] << 4) + (data[7] >> 4);
+
+               wacom->id[idx] = (data[2] << 4) | (data[3] >> 4);
+               switch (wacom->id[idx]) {
+                       case 0x812: /* Inking pen */
+                       case 0x801: /* Intuos3 Inking pen */
+                       case 0x012:
+                               wacom->tool[idx] = BTN_TOOL_PENCIL;
+                               break;
+                       case 0x822: /* Pen */
+                       case 0x842:
+                       case 0x852:
+                       case 0x823: /* Intuos3 Grip Pen */
+                       case 0x813: /* Intuos3 Classic Pen */
+                       case 0x885: /* Intuos3 Marker Pen */
+                       case 0x022:
+                               wacom->tool[idx] = BTN_TOOL_PEN;
+                               break;
+                       case 0x832: /* Stroke pen */
+                       case 0x032:
+                               wacom->tool[idx] = BTN_TOOL_BRUSH;
+                               break;
+                       case 0x007: /* Mouse 4D and 2D */
+                       case 0x09c:
+                       case 0x094:
+                       case 0x017: /* Intuos3 2D Mouse */
+                               wacom->tool[idx] = BTN_TOOL_MOUSE;
+                               break;
+                       case 0x096: /* Lens cursor */
+                       case 0x097: /* Intuos3 Lens cursor */
+                               wacom->tool[idx] = BTN_TOOL_LENS;
+                               break;
+                       case 0x82a: /* Eraser */
+                       case 0x85a:
+                       case 0x91a:
+                       case 0xd1a:
+                       case 0x0fa:
+                       case 0x82b: /* Intuos3 Grip Pen Eraser */
+                       case 0x81b: /* Intuos3 Classic Pen Eraser */
+                       case 0x91b: /* Intuos3 Airbrush Eraser */
+                               wacom->tool[idx] = BTN_TOOL_RUBBER;
+                               break;
+                       case 0xd12:
+                       case 0x912:
+                       case 0x112:
+                       case 0x913: /* Intuos3 Airbrush */
+                               wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
+                               break;
+                       default: /* Unknown tool */
+                               wacom->tool[idx] = BTN_TOOL_PEN;
+               }
+               /* only large I3 support Lens Cursor */
+               if(!((wacom->tool[idx] == BTN_TOOL_LENS) &&
+                               (wacom->features->type == INTUOS3))) {
+                       wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */
+                       wacom_report_key(wcombo, wacom->tool[idx], 1);
+                       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+                       return 2;
+               }
+               return 1;
+       }
+
+       /* Exit report */
+       if ((data[1] & 0xfe) == 0x80) {
+               wacom_report_key(wcombo, wacom->tool[idx], 0);
+               wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */
+               wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+               return 2;
+       }
+       return 0;
+}
+
+static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       unsigned int t;
+
+       /* general pen packet */
+       if ((data[1] & 0xb8) == 0xa0) {
+               t = (data[6] << 2) | ((data[7] >> 6) & 3);
+               wacom_report_abs(wcombo, ABS_PRESSURE, t);
+               wacom_report_abs(wcombo, ABS_TILT_X,
+                               ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+               wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
+               wacom_report_key(wcombo, BTN_STYLUS, data[1] & 2);
+               wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 4);
+               wacom_report_key(wcombo, BTN_TOUCH, t > 10);
+       }
+
+       /* airbrush second packet */
+       if ((data[1] & 0xbc) == 0xb4) {
+               wacom_report_abs(wcombo, ABS_WHEEL,
+                               (data[6] << 2) | ((data[7] >> 6) & 3));
+               wacom_report_abs(wcombo, ABS_TILT_X,
+                               ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+               wacom_report_abs(wcombo, ABS_TILT_Y, data[8] & 0x7f);
+       }
+       return;
+}
+
+static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo)
+{
+       unsigned char *data = wacom->data;
+       unsigned int t;
+       int idx, result;
+
+       if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) {
+               dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
+                return 0;
+       }
+
+       wacom_input_regs(wcombo);
+
+       /* tool number */
+       idx = data[1] & 0x01;
+
+       /* pad packets. Works as a second tool and is always in prox */
+       if (data[0] == 12) {
+               /* initiate the pad as a device */
+               if (wacom->tool[1] != BTN_TOOL_FINGER)
+                       wacom->tool[1] = BTN_TOOL_FINGER;
+
+               wacom_report_key(wcombo, BTN_0, (data[5] & 0x01));
+               wacom_report_key(wcombo, BTN_1, (data[5] & 0x02));
+               wacom_report_key(wcombo, BTN_2, (data[5] & 0x04));
+               wacom_report_key(wcombo, BTN_3, (data[5] & 0x08));
+               wacom_report_key(wcombo, BTN_4, (data[6] & 0x01));
+               wacom_report_key(wcombo, BTN_5, (data[6] & 0x02));
+               wacom_report_key(wcombo, BTN_6, (data[6] & 0x04));
+               wacom_report_key(wcombo, BTN_7, (data[6] & 0x08));
+               wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
+               wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
+
+               if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2])
+                       wacom_report_key(wcombo, wacom->tool[1], 1);
+               else
+                       wacom_report_key(wcombo, wacom->tool[1], 0);
+               wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xffffffff);
+                return 1;
+       }
+
+       /* process in/out prox events */
+       result = wacom_intuos_inout(wacom, wcombo);
+       if (result)
+                return result-1;
+
+       /* Cintiq doesn't send data when RDY bit isn't set */
+       if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40))
+                 return 0;
+
+       if (wacom->features->type >= INTUOS3) {
+               wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1));
+               wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1));
+               wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
+       } else {
+               wacom_report_abs(wcombo, ABS_X, wacom_be16_to_cpu(&data[2]));
+               wacom_report_abs(wcombo, ABS_Y, wacom_be16_to_cpu(&data[4]));
+               wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 3) & 0x1f));
+       }
+
+       /* process general packets */
+       wacom_intuos_general(wacom, wcombo);
+
+       /* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */
+       if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {
+
+               if (data[1] & 0x02) {
+                       /* Rotation packet */
+                       if (wacom->features->type >= INTUOS3) {
+                               /* I3 marker pen rotation reported as wheel
+                                * due to valuator limitation
+                                */
+                               t = (data[6] << 3) | ((data[7] >> 5) & 7);
+                               t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
+                                       ((t-1) / 2 + 450)) : (450 - t / 2) ;
+                               wacom_report_abs(wcombo, ABS_WHEEL, t);
+                       } else {
+                               /* 4D mouse rotation packet */
+                               t = (data[6] << 3) | ((data[7] >> 5) & 7);
+                               wacom_report_abs(wcombo, ABS_RZ, (data[7] & 0x20) ?
+                                       ((t - 1) / 2) : -t / 2);
+                       }
+
+               } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) {
+                       /* 4D mouse packet */
+                       wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
+                       wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
+                       wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04);
+
+                       wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x20);
+                       wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x10);
+                       t = (data[6] << 2) | ((data[7] >> 6) & 3);
+                       wacom_report_abs(wcombo, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
+
+               } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) {
+                       /* 2D mouse packet */
+                       wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x04);
+                       wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x08);
+                       wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x10);
+                       wacom_report_rel(wcombo, REL_WHEEL, (data[8] & 0x01)
+                                                - ((data[8] & 0x02) >> 1));
+
+                       /* I3 2D mouse side buttons */
+                       if (wacom->features->type == INTUOS3) {
+                               wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x40);
+                               wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x20);
+                       }
+
+               } else if (wacom->features->type < INTUOS3) {
+                       /* Lens cursor packets */
+                       wacom_report_key(wcombo, BTN_LEFT,   data[8] & 0x01);
+                       wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02);
+                       wacom_report_key(wcombo, BTN_RIGHT,  data[8] & 0x04);
+                       wacom_report_key(wcombo, BTN_SIDE,   data[8] & 0x10);
+                       wacom_report_key(wcombo, BTN_EXTRA,  data[8] & 0x08);
+               }
+       }
+
+       wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */
+       wacom_report_key(wcombo, wacom->tool[idx], 1);
+       wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+       return 1;
+}
+
+int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo)
+{
+       switch (wacom_wac->features->type) {
+               case PENPARTNER:
+                       return (wacom_penpartner_irq(wacom_wac, wcombo));
+                       break;
+               case PL:
+                       return (wacom_pl_irq(wacom_wac, wcombo));
+                       break;
+               case WACOM_G4:
+               case GRAPHIRE:
+                       return (wacom_graphire_irq(wacom_wac, wcombo));
+                       break;
+               case PTU:
+                       return (wacom_ptu_irq(wacom_wac, wcombo));
+                       break;
+               case INTUOS:
+               case INTUOS3:
+               case INTUOS3L:
+               case CINTIQ:
+                       return (wacom_intuos_irq(wacom_wac, wcombo));
+                       break;
+               default:
+                       return 0;
+       }
+       return 0;
+}
+
+void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
+{
+       switch (wacom_wac->features->type) {
+               case WACOM_G4:
+                       input_dev_g4(input_dev, wacom_wac);
+                       /* fall through */
+               case GRAPHIRE:
+                       input_dev_g(input_dev, wacom_wac);
+                       break;
+               case INTUOS3:
+               case INTUOS3L:
+               case CINTIQ:
+                       input_dev_i3(input_dev, wacom_wac);
+                       /* fall through */
+               case INTUOS:
+                       input_dev_i(input_dev, wacom_wac);
+                       break;
+               case PL:
+               case PTU:
+                       input_dev_pl(input_dev, wacom_wac);
+                       break;
+               case PENPARTNER:
+                       input_dev_pt(input_dev, wacom_wac);
+                       break;
+       }
+       return;
+}
+
+static struct wacom_features wacom_features[] = {
+       { "Wacom Penpartner",    7,   5040,  3780,  255, 32, PENPARTNER,        wacom_sys_irq },
+        { "Wacom Graphire",      8,  10206,  7422,  511, 32, GRAPHIRE, wacom_sys_irq },
+       { "Wacom Graphire2 4x5", 8,  10206,  7422,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Graphire2 5x7", 8,  13918, 10206,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Graphire3",     8,  10208,  7424,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Graphire3 6x8", 8,  16704, 12064,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Graphire4 4x5", 8,  10208,  7424,  511, 32, WACOM_G4,  wacom_sys_irq },
+       { "Wacom Graphire4 6x8", 8,  16704, 12064,  511, 32, WACOM_G4,  wacom_sys_irq },
+       { "Wacom Volito",        8,   5104,  3712,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom PenStation2",   8,   3250,  2320,  255, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Volito2 4x5",   8,   5104,  3712,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Volito2 2x3",   8,   3248,  2320,  511, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom PenPartner2",   8,   3250,  2320,  255, 32, GRAPHIRE,  wacom_sys_irq },
+       { "Wacom Intuos 4x5",   10,  12700, 10600, 1023, 15, INTUOS,    wacom_sys_irq},
+       { "Wacom Intuos 6x8",   10,  20320, 16240, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos 9x12",  10,  30480, 24060, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos 12x12", 10,  30480, 31680, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos 12x18", 10,  45720, 31680, 1023, 15, INTUOS,    wacom_sys_irq},
+       { "Wacom PL400",         8,   5408,  4056,  255, 32, PL,        wacom_sys_irq },
+       { "Wacom PL500",         8,   6144,  4608,  255, 32, PL,        wacom_sys_irq },
+       { "Wacom PL600",         8,   6126,  4604,  255, 32, PL,        wacom_sys_irq },
+       { "Wacom PL600SX",       8,   6260,  5016,  255, 32, PL,        wacom_sys_irq },
+       { "Wacom PL550",         8,   6144,  4608,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom PL800",         8,   7220,  5780,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom PL700",         8,   6758,  5406,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom PL510",         8,   6282,  4762,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom DTU710",        8,  34080, 27660,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom DTF521",        8,   6282,  4762,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom DTF720",        8,   6858,  5506,  511, 32, PL,        wacom_sys_irq },
+       { "Wacom Cintiq Partner",8,  20480, 15360,  511, 32, PTU,       wacom_sys_irq },
+       { "Wacom Intuos2 4x5",   10, 12700, 10600, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos2 9x12",  10, 30480, 24060, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS,    wacom_sys_irq },
+       { "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 15, INTUOS3,   wacom_sys_irq },
+       { "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 15, INTUOS3,   wacom_sys_irq },
+       { "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 15, INTUOS3,   wacom_sys_irq },
+       { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS3L,  wacom_sys_irq },
+       { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS3L,  wacom_sys_irq },
+       { "Wacom Intuos3 6x11",  10, 54204, 31750, 1023, 15, INTUOS3,   wacom_sys_irq },
+       { "Wacom Cintiq 21UX",   10, 87200, 65600, 1023, 15, CINTIQ,    wacom_sys_irq },
+       { "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, INTUOS,    wacom_sys_irq },
+       { }
+};
+
+static struct usb_device_id wacom_ids[] = {
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) },
+       { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
+       { }
+};
+
+const struct usb_device_id * get_device_table(void) {
+        const struct usb_device_id * id_table = wacom_ids;
+        return id_table;
+}
+
+struct wacom_features * get_wacom_feature(const struct usb_device_id * id) {
+        int index = id - wacom_ids;
+        struct wacom_features *wf = &wacom_features[index];
+        return wf;
+}
+
+MODULE_DEVICE_TABLE(usb, wacom_ids);
diff --git a/drivers/usb/input/wacom_wac.h b/drivers/usb/input/wacom_wac.h
new file mode 100644 (file)
index 0000000..ceae7bf
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * drivers/usb/input/wacom_wac.h
+ *
+ * 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 WACOM_WAC_H
+#define WACOM_WAC_H
+
+#define STYLUS_DEVICE_ID       0x02
+#define CURSOR_DEVICE_ID       0x06
+#define ERASER_DEVICE_ID       0x0A
+
+enum {
+       PENPARTNER = 0,
+       GRAPHIRE,
+       WACOM_G4,
+       PTU,
+       PL,
+       INTUOS,
+       INTUOS3,
+       INTUOS3L,
+       CINTIQ,
+       MAX_TYPE
+};
+
+struct wacom_features {
+       char *name;
+       int pktlen;
+       int x_max;
+       int y_max;
+       int pressure_max;
+       int distance_max;
+       int type;
+       usb_complete_t irq;
+};
+
+struct wacom_wac {
+       signed char *data;
+        int tool[2];
+        int id[2];
+        __u32 serial[2];
+       struct wacom_features *features;
+};
+
+#endif
index 7b45fd3de9116715abe9c1c5c19cda527ba739e2..7291e7a2717b4ade9a3a0530ddc2e908cd9fde35 100644 (file)
@@ -971,7 +971,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
                        DRIVER_VERSION, sizeof(DRIVER_VERSION));
 
        /* Register sysfs hooks (don't care about failure) */
-       sysfs_create_group(&intf->dev.kobj, &yld_attr_group);
+       ret = sysfs_create_group(&intf->dev.kobj, &yld_attr_group);
        return 0;
 }
 
index 88928a4be8057e9c286218ecacfecb17334db45e..c29658f69e2a8c0db81dc26a9d1fe9addb1bb96a 100644 (file)
@@ -32,6 +32,16 @@ config USB_EMI26
          To compile this driver as a module, choose M here: the
          module will be called emi26.
 
+config USB_ADUTUX
+       tristate "ADU devices from Ontrak Control Systems (EXPERIMENTAL)"
+       depends on USB && EXPERIMENTAL
+       help
+         Say Y if you want to use an ADU device from Ontrak Control
+         Systems.
+
+         To compile this driver as a module, choose M here.  The module
+         will be called adutux.
+
 config USB_AUERSWALD
        tristate "USB Auerswald ISDN support (EXPERIMENTAL)"
        depends on USB && EXPERIMENTAL
@@ -115,19 +125,36 @@ config USB_CYTHERM
          To compile this driver as a module, choose M here: the
          module will be called cytherm.
 
-config USB_PHIDGETKIT
-       tristate "USB PhidgetKit support"
+config USB_PHIDGET
+       tristate "USB Phidgets drivers"
        depends on USB
        help
-         Say Y here if you want to connect a PhidgetKit USB device from
-         Phidgets Inc.
+         Say Y here to enable the various drivers for devices from
+         Phidgets inc.
+
+config USB_PHIDGETKIT
+       tristate "USB PhidgetInterfaceKit support"
+       depends on USB_PHIDGET
+       help
+         Say Y here if you want to connect a PhidgetInterfaceKit USB device
+         from Phidgets Inc.
 
          To compile this driver as a module, choose M here: the
          module will be called phidgetkit.
 
+config USB_PHIDGETMOTORCONTROL
+       tristate "USB PhidgetMotorControl support"
+       depends on USB_PHIDGET
+       help
+         Say Y here if you want to connect a PhidgetMotorControl USB device
+         from Phidgets Inc.
+
+         To compile this driver as a module, choose M here: the
+         module will be called phidgetmotorcontrol.
+
 config USB_PHIDGETSERVO
        tristate "USB PhidgetServo support"
-       depends on USB
+       depends on USB_PHIDGET
        help
          Say Y here if you want to connect an 1 or 4 Motor PhidgetServo 
          servo controller version 2.0 or 3.0.
@@ -151,6 +178,30 @@ config USB_IDMOUSE
 
          See also <http://www.fs.tum.de/~echtler/idmouse/>.
 
+config USB_FTDI_ELAN
+       tristate "Elan PCMCIA CardBus Adapter USB Client"
+       depends on USB
+       default M
+       help
+         ELAN's Uxxx series of adapters are USB to PCMCIA CardBus adapters.
+         Currently only the U132 adapter is available.
+
+         The U132 is specifically designed for CardBus PC cards that contain
+         an OHCI host controller. Typical PC cards are the Orange Mobile 3G
+         Option GlobeTrotter Fusion card. The U132 adapter will *NOT* work
+         with PC cards that do not contain an OHCI controller. To use a U132
+         adapter you will need this "ftdi-elan" module as well as the "u132-hcd"
+         module which is a USB host controller driver that talks to the OHCI
+         controller within CardBus card that are inserted in the U132 adapter.
+
+         This driver has been tested with a CardBus OHCI USB adapter, and
+         worked with a USB PEN Drive inserted into the first USB port of
+         the PCCARD. A rather pointless thing to do, but useful for testing.
+
+         See also the USB_U132_HCD entry "Elan U132 Adapter Host Controller"
+
+         It is safe to say M here.
+
 config USB_APPLEDISPLAY
        tristate "Apple Cinema Display support"
        depends on USB
index 2927260c5812eed54c2ad21cb001762430d3f4cf..2be70fa259bfe16cc45ebbdcae5db57dd33dcd9d 100644 (file)
@@ -3,22 +3,25 @@
 # (the ones that don't fit into any other categories)
 #
 
+obj-$(CONFIG_USB_ADUTUX)       += adutux.o
 obj-$(CONFIG_USB_AUERSWALD)    += auerswald.o
 obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
 obj-$(CONFIG_USB_CYTHERM)      += cytherm.o
 obj-$(CONFIG_USB_EMI26)                += emi26.o
 obj-$(CONFIG_USB_EMI62)                += emi62.o
+obj-$(CONFIG_USB_FTDI_ELAN)    += ftdi-elan.o
 obj-$(CONFIG_USB_IDMOUSE)      += idmouse.o
 obj-$(CONFIG_USB_LCD)          += usblcd.o
 obj-$(CONFIG_USB_LD)           += ldusb.o
 obj-$(CONFIG_USB_LED)          += usbled.o
 obj-$(CONFIG_USB_LEGOTOWER)    += legousbtower.o
+obj-$(CONFIG_USB_PHIDGET)      += phidget.o
 obj-$(CONFIG_USB_PHIDGETKIT)   += phidgetkit.o
+obj-$(CONFIG_USB_PHIDGETMOTORCONTROL)  += phidgetmotorcontrol.o
 obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o
 obj-$(CONFIG_USB_RIO500)       += rio500.o
 obj-$(CONFIG_USB_TEST)         += usbtest.o
 obj-$(CONFIG_USB_USS720)       += uss720.o
-obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o
 
 obj-$(CONFIG_USB_SISUSBVGA)    += sisusbvga/
 
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c
new file mode 100644 (file)
index 0000000..d396319
--- /dev/null
@@ -0,0 +1,900 @@
+/*
+ * adutux - driver for ADU devices from Ontrak Control Systems
+ * This is an experimental driver. Use at your own risk.
+ * This driver is not supported by Ontrak Control Systems.
+ *
+ * Copyright (c) 2003 John Homppi (SCO, leave this notice here)
+ *
+ * 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.
+ *
+ * derived from the Lego USB Tower driver 0.56:
+ * Copyright (c) 2003 David Glance <davidgsf@sourceforge.net>
+ *               2001 Juergen Stuber <stuber@loria.fr>
+ * that was derived from USB Skeleton driver - 0.5
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_USB_DEBUG
+static int debug = 5;
+#else
+static int debug = 1;
+#endif
+
+/* Use our own dbg macro */
+#undef dbg
+#define dbg(lvl, format, arg...)                                       \
+do {                                                                   \
+       if (debug >= lvl)                                               \
+               printk(KERN_DEBUG __FILE__ " : " format " \n", ## arg); \
+} while (0)
+
+
+/* Version Information */
+#define DRIVER_VERSION "v0.0.13"
+#define DRIVER_AUTHOR "John Homppi"
+#define DRIVER_DESC "adutux (see www.ontrak.net)"
+
+/* Module parameters */
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+/* Define these values to match your device */
+#define ADU_VENDOR_ID 0x0a07
+#define ADU_PRODUCT_ID 0x0064
+
+/* table of devices that work with this driver */
+static struct usb_device_id device_table [] = {
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID) },          /* ADU100 */
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+20) },       /* ADU120 */
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+30) },       /* ADU130 */
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+100) },      /* ADU200 */
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+108) },      /* ADU208 */
+       { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+118) },      /* ADU218 */
+       { }/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+#ifdef CONFIG_USB_DYNAMIC_MINORS
+#define ADU_MINOR_BASE 0
+#else
+#define ADU_MINOR_BASE 67
+#endif
+
+/* we can have up to this number of device plugged in at once */
+#define MAX_DEVICES    16
+
+#define COMMAND_TIMEOUT        (2*HZ)  /* 60 second timeout for a command */
+
+/* Structure to hold all of our device specific stuff */
+struct adu_device {
+       struct semaphore        sem; /* locks this structure */
+       struct usb_device*      udev; /* save off the usb device pointer */
+       struct usb_interface*   interface;
+       unsigned char           minor; /* the starting minor number for this device */
+       char                    serial_number[8];
+
+       int                     open_count; /* number of times this port has been opened */
+
+       char*                   read_buffer_primary;
+       int                     read_buffer_length;
+       char*                   read_buffer_secondary;
+       int                     secondary_head;
+       int                     secondary_tail;
+       spinlock_t              buflock;
+
+       wait_queue_head_t       read_wait;
+       wait_queue_head_t       write_wait;
+
+       char*                   interrupt_in_buffer;
+       struct usb_endpoint_descriptor* interrupt_in_endpoint;
+       struct urb*             interrupt_in_urb;
+       int                     read_urb_finished;
+
+       char*                   interrupt_out_buffer;
+       struct usb_endpoint_descriptor* interrupt_out_endpoint;
+       struct urb*             interrupt_out_urb;
+};
+
+/* prevent races between open() and disconnect */
+static DEFINE_MUTEX(disconnect_mutex);
+static struct usb_driver adu_driver;
+
+static void adu_debug_data(int level, const char *function, int size,
+                          const unsigned char *data)
+{
+       int i;
+
+       if (debug < level)
+               return;
+
+       printk(KERN_DEBUG __FILE__": %s - length = %d, data = ",
+              function, size);
+       for (i = 0; i < size; ++i)
+               printk("%.2x ", data[i]);
+       printk("\n");
+}
+
+/**
+ * adu_abort_transfers
+ *      aborts transfers and frees associated data structures
+ */
+static void adu_abort_transfers(struct adu_device *dev)
+{
+       dbg(2," %s : enter", __FUNCTION__);
+
+       if (dev == NULL) {
+               dbg(1," %s : dev is null", __FUNCTION__);
+               goto exit;
+       }
+
+       if (dev->udev == NULL) {
+               dbg(1," %s : udev is null", __FUNCTION__);
+               goto exit;
+       }
+
+       dbg(2," %s : udev state %d", __FUNCTION__, dev->udev->state);
+       if (dev->udev->state == USB_STATE_NOTATTACHED) {
+               dbg(1," %s : udev is not attached", __FUNCTION__);
+               goto exit;
+       }
+
+       /* shutdown transfer */
+       usb_unlink_urb(dev->interrupt_in_urb);
+       usb_unlink_urb(dev->interrupt_out_urb);
+
+exit:
+       dbg(2," %s : leave", __FUNCTION__);
+}
+
+static void adu_delete(struct adu_device *dev)
+{
+       dbg(2, "%s enter", __FUNCTION__);
+
+       adu_abort_transfers(dev);
+
+       /* free data structures */
+       usb_free_urb(dev->interrupt_in_urb);
+       usb_free_urb(dev->interrupt_out_urb);
+       kfree(dev->read_buffer_primary);
+       kfree(dev->read_buffer_secondary);
+       kfree(dev->interrupt_in_buffer);
+       kfree(dev->interrupt_out_buffer);
+       kfree(dev);
+
+       dbg(2, "%s : leave", __FUNCTION__);
+}
+
+static void adu_interrupt_in_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct adu_device *dev = urb->context;
+
+       dbg(4," %s : enter, status %d", __FUNCTION__, urb->status);
+       adu_debug_data(5, __FUNCTION__, urb->actual_length,
+                      urb->transfer_buffer);
+
+       spin_lock(&dev->buflock);
+
+       if (urb->status != 0) {
+               if ((urb->status != -ENOENT) && (urb->status != -ECONNRESET)) {
+                       dbg(1," %s : nonzero status received: %d",
+                           __FUNCTION__, urb->status);
+               }
+               goto exit;
+       }
+
+       if (urb->actual_length > 0 && dev->interrupt_in_buffer[0] != 0x00) {
+               if (dev->read_buffer_length <
+                   (4 * le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize)) -
+                    (urb->actual_length)) {
+                       memcpy (dev->read_buffer_primary +
+                               dev->read_buffer_length,
+                               dev->interrupt_in_buffer, urb->actual_length);
+
+                       dev->read_buffer_length += urb->actual_length;
+                       dbg(2," %s reading  %d ", __FUNCTION__,
+                           urb->actual_length);
+               } else {
+                       dbg(1," %s : read_buffer overflow", __FUNCTION__);
+               }
+       }
+
+exit:
+       dev->read_urb_finished = 1;
+       spin_unlock(&dev->buflock);
+       /* always wake up so we recover from errors */
+       wake_up_interruptible(&dev->read_wait);
+       adu_debug_data(5, __FUNCTION__, urb->actual_length,
+                      urb->transfer_buffer);
+       dbg(4," %s : leave, status %d", __FUNCTION__, urb->status);
+}
+
+static void adu_interrupt_out_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct adu_device *dev = urb->context;
+
+       dbg(4," %s : enter, status %d", __FUNCTION__, urb->status);
+       adu_debug_data(5,__FUNCTION__, urb->actual_length, urb->transfer_buffer);
+
+       if (urb->status != 0) {
+               if ((urb->status != -ENOENT) &&
+                   (urb->status != -ECONNRESET)) {
+                       dbg(1, " %s :nonzero status received: %d",
+                           __FUNCTION__, urb->status);
+               }
+               goto exit;
+       }
+
+       wake_up_interruptible(&dev->write_wait);
+exit:
+
+       adu_debug_data(5, __FUNCTION__, urb->actual_length,
+                      urb->transfer_buffer);
+       dbg(4," %s : leave, status %d", __FUNCTION__, urb->status);
+}
+
+static int adu_open(struct inode *inode, struct file *file)
+{
+       struct adu_device *dev = NULL;
+       struct usb_interface *interface;
+       int subminor;
+       int retval = 0;
+
+       dbg(2,"%s : enter", __FUNCTION__);
+
+       subminor = iminor(inode);
+
+       mutex_lock(&disconnect_mutex);
+
+       interface = usb_find_interface(&adu_driver, subminor);
+       if (!interface) {
+               err("%s - error, can't find device for minor %d",
+                   __FUNCTION__, subminor);
+               retval = -ENODEV;
+               goto exit_no_device;
+       }
+
+       dev = usb_get_intfdata(interface);
+       if (!dev) {
+               retval = -ENODEV;
+               goto exit_no_device;
+       }
+
+       /* lock this device */
+       if ((retval = down_interruptible(&dev->sem))) {
+               dbg(2, "%s : sem down failed", __FUNCTION__);
+               goto exit_no_device;
+       }
+
+       /* increment our usage count for the device */
+       ++dev->open_count;
+       dbg(2,"%s : open count %d", __FUNCTION__, dev->open_count);
+
+       /* save device in the file's private structure */
+       file->private_data = dev;
+
+       /* initialize in direction */
+       dev->read_buffer_length = 0;
+
+       /* fixup first read by having urb waiting for it */
+       usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
+                        usb_rcvintpipe(dev->udev,
+                                       dev->interrupt_in_endpoint->bEndpointAddress),
+                        dev->interrupt_in_buffer,
+                        le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+                        adu_interrupt_in_callback, dev,
+                        dev->interrupt_in_endpoint->bInterval);
+       /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
+       dev->read_urb_finished = 0;
+       usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+       /* we ignore failure */
+       /* end of fixup for first read */
+
+       up(&dev->sem);
+
+exit_no_device:
+       mutex_unlock(&disconnect_mutex);
+       dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval);
+
+       return retval;
+}
+
+static int adu_release_internal(struct adu_device *dev)
+{
+       int retval = 0;
+
+       dbg(2," %s : enter", __FUNCTION__);
+
+       if (dev->udev == NULL) {
+               /* the device was unplugged before the file was released */
+               adu_delete(dev);
+               goto exit;
+       }
+
+       /* decrement our usage count for the device */
+       --dev->open_count;
+       dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
+       if (dev->open_count <= 0) {
+               adu_abort_transfers(dev);
+               dev->open_count = 0;
+       }
+
+exit:
+       dbg(2," %s : leave", __FUNCTION__);
+       return retval;
+}
+
+static int adu_release(struct inode *inode, struct file *file)
+{
+       struct adu_device *dev = NULL;
+       int retval = 0;
+
+       dbg(2," %s : enter", __FUNCTION__);
+
+       if (file == NULL) {
+               dbg(1," %s : file is NULL", __FUNCTION__);
+               retval = -ENODEV;
+               goto exit;
+       }
+
+       dev = file->private_data;
+
+       if (dev == NULL) {
+               dbg(1," %s : object is NULL", __FUNCTION__);
+               retval = -ENODEV;
+               goto exit;
+       }
+
+       /* lock our device */
+       down(&dev->sem); /* not interruptible */
+
+       if (dev->open_count <= 0) {
+               dbg(1," %s : device not opened", __FUNCTION__);
+               retval = -ENODEV;
+               goto exit;
+       }
+
+       /* do the work */
+       retval = adu_release_internal(dev);
+
+exit:
+       up(&dev->sem);
+       dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+       return retval;
+}
+
+static ssize_t adu_read(struct file *file, __user char *buffer, size_t count,
+                       loff_t *ppos)
+{
+       struct adu_device *dev;
+       size_t bytes_read = 0;
+       size_t bytes_to_read = count;
+       int i;
+       int retval = 0;
+       int timeout = 0;
+       int should_submit = 0;
+       unsigned long flags;
+       DECLARE_WAITQUEUE(wait, current);
+
+       dbg(2," %s : enter, count = %Zd, file=%p", __FUNCTION__, count, file);
+
+       dev = file->private_data;
+       dbg(2," %s : dev=%p", __FUNCTION__, dev);
+       /* lock this object */
+       if (down_interruptible(&dev->sem))
+               return -ERESTARTSYS;
+
+       /* verify that the device wasn't unplugged */
+       if (dev->udev == NULL || dev->minor == 0) {
+               retval = -ENODEV;
+               err("No device or device unplugged %d", retval);
+               goto exit;
+       }
+
+       /* verify that some data was requested */
+       if (count == 0) {
+               dbg(1," %s : read request of 0 bytes", __FUNCTION__);
+               goto exit;
+       }
+
+       timeout = COMMAND_TIMEOUT;
+       dbg(2," %s : about to start looping", __FUNCTION__);
+       while (bytes_to_read) {
+               int data_in_secondary = dev->secondary_tail - dev->secondary_head;
+               dbg(2," %s : while, data_in_secondary=%d, status=%d",
+                   __FUNCTION__, data_in_secondary,
+                   dev->interrupt_in_urb->status);
+
+               if (data_in_secondary) {
+                       /* drain secondary buffer */
+                       int amount = bytes_to_read < data_in_secondary ? bytes_to_read : data_in_secondary;
+                       i = copy_to_user(buffer, dev->read_buffer_secondary+dev->secondary_head, amount);
+                       if (i < 0) {
+                               retval = -EFAULT;
+                               goto exit;
+                       }
+                       dev->secondary_head += (amount - i);
+                       bytes_read += (amount - i);
+                       bytes_to_read -= (amount - i);
+                       if (i) {
+                               retval = bytes_read ? bytes_read : -EFAULT;
+                               goto exit;
+                       }
+               } else {
+                       /* we check the primary buffer */
+                       spin_lock_irqsave (&dev->buflock, flags);
+                       if (dev->read_buffer_length) {
+                               /* we secure access to the primary */
+                               char *tmp;
+                               dbg(2," %s : swap, read_buffer_length = %d",
+                                   __FUNCTION__, dev->read_buffer_length);
+                               tmp = dev->read_buffer_secondary;
+                               dev->read_buffer_secondary = dev->read_buffer_primary;
+                               dev->read_buffer_primary = tmp;
+                               dev->secondary_head = 0;
+                               dev->secondary_tail = dev->read_buffer_length;
+                               dev->read_buffer_length = 0;
+                               spin_unlock_irqrestore(&dev->buflock, flags);
+                               /* we have a free buffer so use it */
+                               should_submit = 1;
+                       } else {
+                               /* even the primary was empty - we may need to do IO */
+                               if (dev->interrupt_in_urb->status == -EINPROGRESS) {
+                                       /* somebody is doing IO */
+                                       spin_unlock_irqrestore(&dev->buflock, flags);
+                                       dbg(2," %s : submitted already", __FUNCTION__);
+                               } else {
+                                       /* we must initiate input */
+                                       dbg(2," %s : initiate input", __FUNCTION__);
+                                       dev->read_urb_finished = 0;
+
+                                       usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
+                                                        usb_rcvintpipe(dev->udev,
+                                                                       dev->interrupt_in_endpoint->bEndpointAddress),
+                                                        dev->interrupt_in_buffer,
+                                                        le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+                                                        adu_interrupt_in_callback,
+                                                        dev,
+                                                        dev->interrupt_in_endpoint->bInterval);
+                                       retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+                                       if (!retval) {
+                                               spin_unlock_irqrestore(&dev->buflock, flags);
+                                               dbg(2," %s : submitted OK", __FUNCTION__);
+                                       } else {
+                                               if (retval == -ENOMEM) {
+                                                       retval = bytes_read ? bytes_read : -ENOMEM;
+                                               }
+                                               spin_unlock_irqrestore(&dev->buflock, flags);
+                                               dbg(2," %s : submit failed", __FUNCTION__);
+                                               goto exit;
+                                       }
+                               }
+
+                               /* we wait for I/O to complete */
+                               set_current_state(TASK_INTERRUPTIBLE);
+                               add_wait_queue(&dev->read_wait, &wait);
+                               if (!dev->read_urb_finished)
+                                       timeout = schedule_timeout(COMMAND_TIMEOUT);
+                               else
+                                       set_current_state(TASK_RUNNING);
+                               remove_wait_queue(&dev->read_wait, &wait);
+
+                               if (timeout <= 0) {
+                                       dbg(2," %s : timeout", __FUNCTION__);
+                                       retval = bytes_read ? bytes_read : -ETIMEDOUT;
+                                       goto exit;
+                               }
+
+                               if (signal_pending(current)) {
+                                       dbg(2," %s : signal pending", __FUNCTION__);
+                                       retval = bytes_read ? bytes_read : -EINTR;
+                                       goto exit;
+                               }
+                       }
+               }
+       }
+
+       retval = bytes_read;
+       /* if the primary buffer is empty then use it */
+       if (should_submit && !dev->interrupt_in_urb->status==-EINPROGRESS) {
+               usb_fill_int_urb(dev->interrupt_in_urb,dev->udev,
+                                usb_rcvintpipe(dev->udev,
+                                               dev->interrupt_in_endpoint->bEndpointAddress),
+                                               dev->interrupt_in_buffer,
+                                               le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
+                                               adu_interrupt_in_callback,
+                                               dev,
+                                               dev->interrupt_in_endpoint->bInterval);
+               /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
+               dev->read_urb_finished = 0;
+               usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
+               /* we ignore failure */
+       }
+
+exit:
+       /* unlock the device */
+       up(&dev->sem);
+
+       dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+       return retval;
+}
+
+static ssize_t adu_write(struct file *file, const __user char *buffer,
+                        size_t count, loff_t *ppos)
+{
+       struct adu_device *dev;
+       size_t bytes_written = 0;
+       size_t bytes_to_write;
+       size_t buffer_size;
+       int retval = 0;
+       int timeout = 0;
+
+       dbg(2," %s : enter, count = %Zd", __FUNCTION__, count);
+
+       dev = file->private_data;
+
+       /* lock this object */
+       down_interruptible(&dev->sem);
+
+       /* verify that the device wasn't unplugged */
+       if (dev->udev == NULL || dev->minor == 0) {
+               retval = -ENODEV;
+               err("No device or device unplugged %d", retval);
+               goto exit;
+       }
+
+       /* verify that we actually have some data to write */
+       if (count == 0) {
+               dbg(1," %s : write request of 0 bytes", __FUNCTION__);
+               goto exit;
+       }
+
+
+       while (count > 0) {
+               if (dev->interrupt_out_urb->status == -EINPROGRESS) {
+                       timeout = COMMAND_TIMEOUT;
+
+                       while (timeout > 0) {
+                               if (signal_pending(current)) {
+                               dbg(1," %s : interrupted", __FUNCTION__);
+                               retval = -EINTR;
+                               goto exit;
+                       }
+                       up(&dev->sem);
+                       timeout = interruptible_sleep_on_timeout(&dev->write_wait, timeout);
+                       down_interruptible(&dev->sem);
+                       if (timeout > 0) {
+                               break;
+                       }
+                       dbg(1," %s : interrupted timeout: %d", __FUNCTION__, timeout);
+               }
+
+
+               dbg(1," %s : final timeout: %d", __FUNCTION__, timeout);
+
+               if (timeout == 0) {
+                       dbg(1, "%s - command timed out.", __FUNCTION__);
+                       retval = -ETIMEDOUT;
+                       goto exit;
+               }
+
+               dbg(4," %s : in progress, count = %Zd", __FUNCTION__, count);
+
+               } else {
+                       dbg(4," %s : sending, count = %Zd", __FUNCTION__, count);
+
+                       /* write the data into interrupt_out_buffer from userspace */
+                       buffer_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize);
+                       bytes_to_write = count > buffer_size ? buffer_size : count;
+                       dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd",
+                           __FUNCTION__, buffer_size, count, bytes_to_write);
+
+                       if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) {
+                               retval = -EFAULT;
+                               goto exit;
+                       }
+
+                       /* send off the urb */
+                       usb_fill_int_urb(
+                               dev->interrupt_out_urb,
+                               dev->udev,
+                               usb_sndintpipe(dev->udev, dev->interrupt_out_endpoint->bEndpointAddress),
+                               dev->interrupt_out_buffer,
+                               bytes_to_write,
+                               adu_interrupt_out_callback,
+                               dev,
+                               dev->interrupt_in_endpoint->bInterval);
+                       /* dev->interrupt_in_urb->transfer_flags |= URB_ASYNC_UNLINK; */
+                       dev->interrupt_out_urb->actual_length = bytes_to_write;
+                       retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
+                       if (retval < 0) {
+                               err("Couldn't submit interrupt_out_urb %d", retval);
+                               goto exit;
+                       }
+
+                       buffer += bytes_to_write;
+                       count -= bytes_to_write;
+
+                       bytes_written += bytes_to_write;
+               }
+       }
+
+       retval = bytes_written;
+
+exit:
+       /* unlock the device */
+       up(&dev->sem);
+
+       dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
+
+       return retval;
+}
+
+/* file operations needed when we register this driver */
+static struct file_operations adu_fops = {
+       .owner = THIS_MODULE,
+       .read  = adu_read,
+       .write = adu_write,
+       .open = adu_open,
+       .release = adu_release,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
+ */
+static struct usb_class_driver adu_class = {
+       .name = "usb/adutux%d",
+       .fops = &adu_fops,
+       .minor_base = ADU_MINOR_BASE,
+};
+
+/**
+ * adu_probe
+ *
+ * Called by the usb core when a new device is connected that it thinks
+ * this driver might be interested in.
+ */
+static int adu_probe(struct usb_interface *interface,
+                    const struct usb_device_id *id)
+{
+       struct usb_device *udev = interface_to_usbdev(interface);
+       struct adu_device *dev = NULL;
+       struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       int retval = -ENODEV;
+       int in_end_size;
+       int out_end_size;
+       int i;
+
+       dbg(2," %s : enter", __FUNCTION__);
+
+       if (udev == NULL) {
+               dev_err(&interface->dev, "udev is NULL.\n");
+               goto exit;
+       }
+
+       /* allocate memory for our device state and intialize it */
+       dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL);
+       if (dev == NULL) {
+               dev_err(&interface->dev, "Out of memory\n");
+               retval = -ENOMEM;
+               goto exit;
+       }
+
+       init_MUTEX(&dev->sem);
+       spin_lock_init(&dev->buflock);
+       dev->udev = udev;
+       init_waitqueue_head(&dev->read_wait);
+       init_waitqueue_head(&dev->write_wait);
+
+       iface_desc = &interface->altsetting[0];
+
+       /* set up the endpoint information */
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+
+               if (usb_endpoint_is_int_in(endpoint))
+                       dev->interrupt_in_endpoint = endpoint;
+
+               if (usb_endpoint_is_int_out(endpoint))
+                       dev->interrupt_out_endpoint = endpoint;
+       }
+       if (dev->interrupt_in_endpoint == NULL) {
+               dev_err(&interface->dev, "interrupt in endpoint not found\n");
+               goto error;
+       }
+       if (dev->interrupt_out_endpoint == NULL) {
+               dev_err(&interface->dev, "interrupt out endpoint not found\n");
+               goto error;
+       }
+
+       in_end_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
+       out_end_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize);
+
+       dev->read_buffer_primary = kmalloc((4 * in_end_size), GFP_KERNEL);
+       if (!dev->read_buffer_primary) {
+               dev_err(&interface->dev, "Couldn't allocate read_buffer_primary\n");
+               retval = -ENOMEM;
+               goto error;
+       }
+
+       /* debug code prime the buffer */
+       memset(dev->read_buffer_primary, 'a', in_end_size);
+       memset(dev->read_buffer_primary + in_end_size, 'b', in_end_size);
+       memset(dev->read_buffer_primary + (2 * in_end_size), 'c', in_end_size);
+       memset(dev->read_buffer_primary + (3 * in_end_size), 'd', in_end_size);
+
+       dev->read_buffer_secondary = kmalloc((4 * in_end_size), GFP_KERNEL);
+       if (!dev->read_buffer_secondary) {
+               dev_err(&interface->dev, "Couldn't allocate read_buffer_secondary\n");
+               retval = -ENOMEM;
+               goto error;
+       }
+
+       /* debug code prime the buffer */
+       memset(dev->read_buffer_secondary, 'e', in_end_size);
+       memset(dev->read_buffer_secondary + in_end_size, 'f', in_end_size);
+       memset(dev->read_buffer_secondary + (2 * in_end_size), 'g', in_end_size);
+       memset(dev->read_buffer_secondary + (3 * in_end_size), 'h', in_end_size);
+
+       dev->interrupt_in_buffer = kmalloc(in_end_size, GFP_KERNEL);
+       if (!dev->interrupt_in_buffer) {
+               dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
+               goto error;
+       }
+
+       /* debug code prime the buffer */
+       memset(dev->interrupt_in_buffer, 'i', in_end_size);
+
+       dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->interrupt_in_urb) {
+               dev_err(&interface->dev, "Couldn't allocate interrupt_in_urb\n");
+               goto error;
+       }
+       dev->interrupt_out_buffer = kmalloc(out_end_size, GFP_KERNEL);
+       if (!dev->interrupt_out_buffer) {
+               dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
+               goto error;
+       }
+       dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!dev->interrupt_out_urb) {
+               dev_err(&interface->dev, "Couldn't allocate interrupt_out_urb\n");
+               goto error;
+       }
+
+       if (!usb_string(udev, udev->descriptor.iSerialNumber, dev->serial_number,
+                       sizeof(dev->serial_number))) {
+               dev_err(&interface->dev, "Could not retrieve serial number\n");
+               goto error;
+       }
+       dbg(2," %s : serial_number=%s", __FUNCTION__, dev->serial_number);
+
+       /* we can register the device now, as it is ready */
+       usb_set_intfdata(interface, dev);
+
+       retval = usb_register_dev(interface, &adu_class);
+
+       if (retval) {
+               /* something prevented us from registering this driver */
+               dev_err(&interface->dev, "Not able to get a minor for this device.\n");
+               usb_set_intfdata(interface, NULL);
+               goto error;
+       }
+
+       dev->minor = interface->minor;
+
+       /* let the user know what node this device is now attached to */
+       dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d",
+                udev->descriptor.idProduct, dev->serial_number,
+                (dev->minor - ADU_MINOR_BASE));
+exit:
+       dbg(2," %s : leave, return value %p (dev)", __FUNCTION__, dev);
+
+       return retval;
+
+error:
+       adu_delete(dev);
+       return retval;
+}
+
+/**
+ * adu_disconnect
+ *
+ * Called by the usb core when the device is removed from the system.
+ */
+static void adu_disconnect(struct usb_interface *interface)
+{
+       struct adu_device *dev;
+       int minor;
+
+       dbg(2," %s : enter", __FUNCTION__);
+
+       mutex_lock(&disconnect_mutex); /* not interruptible */
+
+       dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       down(&dev->sem); /* not interruptible */
+
+       minor = dev->minor;
+
+       /* give back our minor */
+       usb_deregister_dev(interface, &adu_class);
+       dev->minor = 0;
+
+       /* if the device is not opened, then we clean up right now */
+       dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
+       if (!dev->open_count) {
+               up(&dev->sem);
+               adu_delete(dev);
+       } else {
+               dev->udev = NULL;
+               up(&dev->sem);
+       }
+
+       mutex_unlock(&disconnect_mutex);
+
+       dev_info(&interface->dev, "ADU device adutux%d now disconnected",
+                (minor - ADU_MINOR_BASE));
+
+       dbg(2," %s : leave", __FUNCTION__);
+}
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver adu_driver = {
+       .name = "adutux",
+       .probe = adu_probe,
+       .disconnect = adu_disconnect,
+       .id_table = device_table,
+};
+
+static int __init adu_init(void)
+{
+       int result;
+
+       dbg(2," %s : enter", __FUNCTION__);
+
+       /* register this driver with the USB subsystem */
+       result = usb_register(&adu_driver);
+       if (result < 0) {
+               err("usb_register failed for the "__FILE__" driver. "
+                   "Error number %d", result);
+               goto exit;
+       }
+
+       info("adutux " DRIVER_DESC " " DRIVER_VERSION);
+       info("adutux is an experimental driver. Use at your own risk");
+
+exit:
+       dbg(2," %s : leave, return value %d", __FUNCTION__, result);
+
+       return result;
+}
+
+static void __exit adu_exit(void)
+{
+       dbg(2," %s : enter", __FUNCTION__);
+       /* deregister this driver with the USB subsystem */
+       usb_deregister(&adu_driver);
+       dbg(2," %s : leave", __FUNCTION__);
+}
+
+module_init(adu_init);
+module_exit(adu_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
index 1fef36e71c573ed10dc05b2de5240816e87fa0c5..4fd2110b34110066606726197e966eb271b00846 100644 (file)
@@ -806,7 +806,7 @@ static void auerbuf_releasebuf( pauerbuf_t bp)
 0              Initial, OK
 -EINPROGRESS   during submission until end
 -ENOENT                if urb is unlinked
--ETIMEDOUT     Transfer timed out, NAK
+-ETIME         Device did not respond
 -ENOMEM                Memory Overflow
 -ENODEV                Specified USB-device or bus doesn't exist
 -ENXIO         URB already queued
@@ -832,7 +832,7 @@ static int auerswald_status_retry (int status)
 {
        switch (status) {
        case 0:
-       case -ETIMEDOUT:
+       case -ETIME:
        case -EOVERFLOW:
        case -EAGAIN:
        case -EPIPE:
@@ -1858,7 +1858,7 @@ static int auerchar_release (struct inode *inode, struct file *file)
 
 /*----------------------------------------------------------------------*/
 /* File operation structure                                             */
-static struct file_operations auerswald_fops =
+static const struct file_operations auerswald_fops =
 {
        .owner =        THIS_MODULE,
        .llseek =       no_llseek,
index 9c46746d5d002ab0881918e39ab363f71a4fb926..b63b5f34b2aa5f0f79b7103c9e14ce9e89f2b2a7 100644 (file)
@@ -209,7 +209,7 @@ static int cypress_probe(struct usb_interface *interface,
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (dev == NULL) {
                dev_err(&interface->dev, "Out of memory!\n");
-               goto error;
+               goto error_mem;
        }
 
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
@@ -218,15 +218,26 @@ static int cypress_probe(struct usb_interface *interface,
        usb_set_intfdata(interface, dev);
 
        /* create device attribute files */
-       device_create_file(&interface->dev, &dev_attr_port0);
-       device_create_file(&interface->dev, &dev_attr_port1);
+       retval = device_create_file(&interface->dev, &dev_attr_port0);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_port1);
+       if (retval)
+               goto error;
 
        /* let the user know that the device is now attached */
        dev_info(&interface->dev,
                 "Cypress CY7C63xxx device now attached\n");
+       return 0;
 
-       retval = 0;
 error:
+       device_remove_file(&interface->dev, &dev_attr_port0);
+       device_remove_file(&interface->dev, &dev_attr_port1);
+       usb_set_intfdata(interface, NULL);
+       usb_put_dev(dev->udev);
+       kfree(dev);
+
+error_mem:
        return retval;
 }
 
index b20bec445552007b23d0008bc6998a3f717244af..04e87acd6e46007cec2449ffe34c58257d55c6a8 100644 (file)
@@ -353,7 +353,7 @@ static int cytherm_probe(struct usb_interface *interface,
        dev = kzalloc (sizeof(struct usb_cytherm), GFP_KERNEL);
        if (dev == NULL) {
                dev_err (&interface->dev, "Out of memory\n");
-               goto error;
+               goto error_mem;
        }
 
        dev->udev = usb_get_dev(udev);
@@ -362,18 +362,35 @@ static int cytherm_probe(struct usb_interface *interface,
 
        dev->brightness = 0xFF;
 
-       device_create_file(&interface->dev, &dev_attr_brightness);   
-       device_create_file(&interface->dev, &dev_attr_temp);
-       device_create_file(&interface->dev, &dev_attr_button);
-       device_create_file(&interface->dev, &dev_attr_port0);
-       device_create_file(&interface->dev, &dev_attr_port1);
+       retval = device_create_file(&interface->dev, &dev_attr_brightness);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_temp);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_button);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_port0);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_port1);
+       if (retval)
+               goto error;
 
-       dev_info (&interface->dev, 
+       dev_info (&interface->dev,
                  "Cypress thermometer device now attached\n");
        return 0;
-
- error:
+error:
+       device_remove_file(&interface->dev, &dev_attr_brightness);
+       device_remove_file(&interface->dev, &dev_attr_temp);
+       device_remove_file(&interface->dev, &dev_attr_button);
+       device_remove_file(&interface->dev, &dev_attr_port0);
+       device_remove_file(&interface->dev, &dev_attr_port1);
+       usb_set_intfdata (interface, NULL);
+       usb_put_dev(dev->udev);
        kfree(dev);
+error_mem:
        return retval;
 }
 
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
new file mode 100644 (file)
index 0000000..b88a094
--- /dev/null
@@ -0,0 +1,2809 @@
+/*
+* USB FTDI client driver for Elan Digital Systems's Uxxx adapters
+*
+* Copyright(C) 2006 Elan Digital Systems Limited
+* http://www.elandigitalsystems.com
+*
+* Author and Maintainer - Tony Olech - Elan Digital Systems
+* tony.olech@elandigitalsystems.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.
+*
+*
+* This driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
+* based on various USB client drivers in the 2.6.15 linux kernel
+* with constant reference to the 3rd Edition of Linux Device Drivers
+* published by O'Reilly
+*
+* The U132 adapter is a USB to CardBus adapter specifically designed
+* for PC cards that contain an OHCI host controller. Typical PC cards
+* are the Orange Mobile 3G Option GlobeTrotter Fusion card.
+*
+* The U132 adapter will *NOT *work with PC cards that do not contain
+* an OHCI controller. A simple way to test whether a PC card has an
+* OHCI controller as an interface is to insert the PC card directly
+* into a laptop(or desktop) with a CardBus slot and if "lspci" shows
+* a new USB controller and "lsusb -v" shows a new OHCI Host Controller
+* then there is a good chance that the U132 adapter will support the
+* PC card.(you also need the specific client driver for the PC card)
+*
+* Please inform the Author and Maintainer about any PC cards that
+* contain OHCI Host Controller and work when directly connected to
+* an embedded CardBus slot but do not work when they are connected
+* via an ELAN U132 adapter.
+*
+*/
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/ioctl.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <asm/uaccess.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+MODULE_AUTHOR("Tony Olech");
+MODULE_DESCRIPTION("FTDI ELAN driver");
+MODULE_LICENSE("GPL");
+#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
+extern struct platform_driver u132_platform_driver;
+static struct workqueue_struct *status_queue;
+static struct workqueue_struct *command_queue;
+static struct workqueue_struct *respond_queue;
+/*
+* ftdi_module_lock exists to protect access to global variables
+*
+*/
+static struct semaphore ftdi_module_lock;
+static int ftdi_instances = 0;
+static struct list_head ftdi_static_list;
+/*
+* end of the global variables protected by ftdi_module_lock
+*/
+#include "usb_u132.h"
+#define TD_DEVNOTRESP 5
+/* Define these values to match your devices*/
+#define USB_FTDI_ELAN_VENDOR_ID 0x0403
+#define USB_FTDI_ELAN_PRODUCT_ID 0xd6ea
+/* table of devices that work with this driver*/
+static struct usb_device_id ftdi_elan_table[] = {
+        {USB_DEVICE(USB_FTDI_ELAN_VENDOR_ID, USB_FTDI_ELAN_PRODUCT_ID)},
+        { /* Terminating entry */ }
+};
+
+MODULE_DEVICE_TABLE(usb, ftdi_elan_table);
+/* only the jtag(firmware upgrade device) interface requires
+* a device file and corresponding minor number, but the
+* interface is created unconditionally - I suppose it could
+* be configured or not according to a module parameter.
+* But since we(now) require one interface per device,
+* and since it unlikely that a normal installation would
+* require more than a couple of elan-ftdi devices, 8 seems
+* like a reasonable limit to have here, and if someone
+* really requires more than 8 devices, then they can frig the
+* code and recompile
+*/
+#define USB_FTDI_ELAN_MINOR_BASE 192
+#define COMMAND_BITS 5
+#define COMMAND_SIZE (1<<COMMAND_BITS)
+#define COMMAND_MASK (COMMAND_SIZE-1)
+struct u132_command {
+        u8 header;
+        u16 length;
+        u8 address;
+        u8 width;
+        u32 value;
+        int follows;
+        void *buffer;
+};
+#define RESPOND_BITS 5
+#define RESPOND_SIZE (1<<RESPOND_BITS)
+#define RESPOND_MASK (RESPOND_SIZE-1)
+struct u132_respond {
+        u8 header;
+        u8 address;
+        u32 *value;
+        int *result;
+        struct completion wait_completion;
+};
+struct u132_target {
+        void *endp;
+        struct urb *urb;
+        int toggle_bits;
+        int error_count;
+        int condition_code;
+        int repeat_number;
+        int halted;
+        int skipped;
+        int actual;
+        int non_null;
+        int active;
+        int abandoning;
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+                int toggle_bits, int error_count, int condition_code,
+                int repeat_number, int halted, int skipped, int actual,
+                int non_null);
+};
+/* Structure to hold all of our device specific stuff*/
+struct usb_ftdi {
+        struct list_head ftdi_list;
+        struct semaphore u132_lock;
+        int command_next;
+        int command_head;
+        struct u132_command command[COMMAND_SIZE];
+        int respond_next;
+        int respond_head;
+        struct u132_respond respond[RESPOND_SIZE];
+        struct u132_target target[4];
+        char device_name[16];
+        unsigned synchronized:1;
+        unsigned enumerated:1;
+        unsigned registered:1;
+        unsigned initialized:1;
+        unsigned card_ejected:1;
+        int function;
+        int sequence_num;
+        int disconnected;
+        int gone_away;
+        int stuck_status;
+        int status_queue_delay;
+        struct semaphore sw_lock;
+        struct usb_device *udev;
+        struct usb_interface *interface;
+        struct usb_class_driver *class;
+        struct work_struct status_work;
+        struct work_struct command_work;
+        struct work_struct respond_work;
+        struct u132_platform_data platform_data;
+        struct resource resources[0];
+        struct platform_device platform_dev;
+        unsigned char *bulk_in_buffer;
+        size_t bulk_in_size;
+        size_t bulk_in_last;
+        size_t bulk_in_left;
+        __u8 bulk_in_endpointAddr;
+        __u8 bulk_out_endpointAddr;
+        struct kref kref;
+        u32 controlreg;
+        u8 response[4 + 1024];
+        int expected;
+        int recieved;
+        int ed_found;
+};
+#define kref_to_usb_ftdi(d) container_of(d, struct usb_ftdi, kref)
+#define platform_device_to_usb_ftdi(d) container_of(d, struct usb_ftdi, \
+        platform_dev)
+static struct usb_driver ftdi_elan_driver;
+static void ftdi_elan_delete(struct kref *kref)
+{
+        struct usb_ftdi *ftdi = kref_to_usb_ftdi(kref);
+        dev_warn(&ftdi->udev->dev, "FREEING ftdi=%p\n", ftdi);
+        usb_put_dev(ftdi->udev);
+        ftdi->disconnected += 1;
+        down(&ftdi_module_lock);
+        list_del_init(&ftdi->ftdi_list);
+        ftdi_instances -= 1;
+        up(&ftdi_module_lock);
+        kfree(ftdi->bulk_in_buffer);
+        ftdi->bulk_in_buffer = NULL;
+}
+
+static void ftdi_elan_put_kref(struct usb_ftdi *ftdi)
+{
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+static void ftdi_elan_get_kref(struct usb_ftdi *ftdi)
+{
+        kref_get(&ftdi->kref);
+}
+
+static void ftdi_elan_init_kref(struct usb_ftdi *ftdi)
+{
+        kref_init(&ftdi->kref);
+}
+
+static void ftdi_status_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(status_queue, &ftdi->status_work, delta))
+                        return;
+        } else if (queue_work(status_queue, &ftdi->status_work))
+                return;
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+        return;
+}
+
+static void ftdi_status_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(status_queue, &ftdi->status_work, delta))
+                        kref_get(&ftdi->kref);
+        } else if (queue_work(status_queue, &ftdi->status_work))
+                kref_get(&ftdi->kref);
+        return;
+}
+
+static void ftdi_status_cancel_work(struct usb_ftdi *ftdi)
+{
+        if (cancel_delayed_work(&ftdi->status_work))
+                kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+static void ftdi_command_requeue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(command_queue, &ftdi->command_work,
+                        delta))
+                        return;
+        } else if (queue_work(command_queue, &ftdi->command_work))
+                return;
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+        return;
+}
+
+static void ftdi_command_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(command_queue, &ftdi->command_work,
+                        delta))
+                        kref_get(&ftdi->kref);
+        } else if (queue_work(command_queue, &ftdi->command_work))
+                kref_get(&ftdi->kref);
+        return;
+}
+
+static void ftdi_command_cancel_work(struct usb_ftdi *ftdi)
+{
+        if (cancel_delayed_work(&ftdi->command_work))
+                kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+static void ftdi_response_requeue_work(struct usb_ftdi *ftdi,
+        unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(respond_queue, &ftdi->respond_work,
+                        delta))
+                        return;
+        } else if (queue_work(respond_queue, &ftdi->respond_work))
+                return;
+        kref_put(&ftdi->kref, ftdi_elan_delete);
+        return;
+}
+
+static void ftdi_respond_queue_work(struct usb_ftdi *ftdi, unsigned int delta)
+{
+        if (delta > 0) {
+                if (queue_delayed_work(respond_queue, &ftdi->respond_work,
+                        delta))
+                        kref_get(&ftdi->kref);
+        } else if (queue_work(respond_queue, &ftdi->respond_work))
+                kref_get(&ftdi->kref);
+        return;
+}
+
+static void ftdi_response_cancel_work(struct usb_ftdi *ftdi)
+{
+        if (cancel_delayed_work(&ftdi->respond_work))
+                kref_put(&ftdi->kref, ftdi_elan_delete);
+}
+
+void ftdi_elan_gone_away(struct platform_device *pdev)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        ftdi->gone_away += 1;
+        ftdi_elan_put_kref(ftdi);
+}
+
+
+EXPORT_SYMBOL_GPL(ftdi_elan_gone_away);
+void ftdi_release_platform_dev(struct device *dev)
+{
+        dev->parent = NULL;
+}
+
+static void ftdi_elan_do_callback(struct usb_ftdi *ftdi,
+        struct u132_target *target, u8 *buffer, int length);
+static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi);
+static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi);
+static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi);
+static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi);
+static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi);
+static int ftdi_elan_synchronize(struct usb_ftdi *ftdi);
+static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi);
+static int ftdi_elan_command_engine(struct usb_ftdi *ftdi);
+static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi);
+static int ftdi_elan_hcd_init(struct usb_ftdi *ftdi)
+{
+        int result;
+        if (ftdi->platform_dev.dev.parent)
+                return -EBUSY;
+        ftdi_elan_get_kref(ftdi);
+        ftdi->platform_data.potpg = 100;
+        ftdi->platform_data.reset = NULL;
+        ftdi->platform_dev.id = ftdi->sequence_num;
+        ftdi->platform_dev.resource = ftdi->resources;
+        ftdi->platform_dev.num_resources = ARRAY_SIZE(ftdi->resources);
+        ftdi->platform_dev.dev.platform_data = &ftdi->platform_data;
+        ftdi->platform_dev.dev.parent = NULL;
+        ftdi->platform_dev.dev.release = ftdi_release_platform_dev;
+        ftdi->platform_dev.dev.dma_mask = NULL;
+        snprintf(ftdi->device_name, sizeof(ftdi->device_name), "u132_hcd");
+        ftdi->platform_dev.name = ftdi->device_name;
+        dev_info(&ftdi->udev->dev, "requesting module '%s'\n", "u132_hcd");
+        request_module("u132_hcd");
+        dev_info(&ftdi->udev->dev, "registering '%s'\n",
+                ftdi->platform_dev.name);
+        result = platform_device_register(&ftdi->platform_dev);
+        return result;
+}
+
+static void ftdi_elan_abandon_completions(struct usb_ftdi *ftdi)
+{
+        down(&ftdi->u132_lock);
+        while (ftdi->respond_next > ftdi->respond_head) {
+                struct u132_respond *respond = &ftdi->respond[RESPOND_MASK &
+                        ftdi->respond_head++];
+                *respond->result = -ESHUTDOWN;
+                *respond->value = 0;
+                complete(&respond->wait_completion);
+        } up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_abandon_targets(struct usb_ftdi *ftdi)
+{
+        int ed_number = 4;
+        down(&ftdi->u132_lock);
+        while (ed_number-- > 0) {
+                struct u132_target *target = &ftdi->target[ed_number];
+                if (target->active == 1) {
+                        target->condition_code = TD_DEVNOTRESP;
+                        up(&ftdi->u132_lock);
+                        ftdi_elan_do_callback(ftdi, target, NULL, 0);
+                        down(&ftdi->u132_lock);
+                }
+        }
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_flush_targets(struct usb_ftdi *ftdi)
+{
+        int ed_number = 4;
+        down(&ftdi->u132_lock);
+        while (ed_number-- > 0) {
+                struct u132_target *target = &ftdi->target[ed_number];
+                target->abandoning = 1;
+              wait_1:if (target->active == 1) {
+                        int command_size = ftdi->command_next -
+                                ftdi->command_head;
+                        if (command_size < COMMAND_SIZE) {
+                                struct u132_command *command = &ftdi->command[
+                                        COMMAND_MASK & ftdi->command_next];
+                                command->header = 0x80 | (ed_number << 5) | 0x4;
+                                command->length = 0x00;
+                                command->address = 0x00;
+                                command->width = 0x00;
+                                command->follows = 0;
+                                command->value = 0;
+                                command->buffer = &command->value;
+                                ftdi->command_next += 1;
+                                ftdi_elan_kick_command_queue(ftdi);
+                        } else {
+                                up(&ftdi->u132_lock);
+                                msleep(100);
+                                down(&ftdi->u132_lock);
+                                goto wait_1;
+                        }
+                }
+              wait_2:if (target->active == 1) {
+                        int command_size = ftdi->command_next -
+                                ftdi->command_head;
+                        if (command_size < COMMAND_SIZE) {
+                                struct u132_command *command = &ftdi->command[
+                                        COMMAND_MASK & ftdi->command_next];
+                                command->header = 0x90 | (ed_number << 5);
+                                command->length = 0x00;
+                                command->address = 0x00;
+                                command->width = 0x00;
+                                command->follows = 0;
+                                command->value = 0;
+                                command->buffer = &command->value;
+                                ftdi->command_next += 1;
+                                ftdi_elan_kick_command_queue(ftdi);
+                        } else {
+                                up(&ftdi->u132_lock);
+                                msleep(100);
+                                down(&ftdi->u132_lock);
+                                goto wait_2;
+                        }
+                }
+        }
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_cancel_targets(struct usb_ftdi *ftdi)
+{
+        int ed_number = 4;
+        down(&ftdi->u132_lock);
+        while (ed_number-- > 0) {
+                struct u132_target *target = &ftdi->target[ed_number];
+                target->abandoning = 1;
+              wait:if (target->active == 1) {
+                        int command_size = ftdi->command_next -
+                                ftdi->command_head;
+                        if (command_size < COMMAND_SIZE) {
+                                struct u132_command *command = &ftdi->command[
+                                        COMMAND_MASK & ftdi->command_next];
+                                command->header = 0x80 | (ed_number << 5) | 0x4;
+                                command->length = 0x00;
+                                command->address = 0x00;
+                                command->width = 0x00;
+                                command->follows = 0;
+                                command->value = 0;
+                                command->buffer = &command->value;
+                                ftdi->command_next += 1;
+                                ftdi_elan_kick_command_queue(ftdi);
+                        } else {
+                                up(&ftdi->u132_lock);
+                                msleep(100);
+                                down(&ftdi->u132_lock);
+                                goto wait;
+                        }
+                }
+        }
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        up(&ftdi->u132_lock);
+}
+
+static void ftdi_elan_kick_command_queue(struct usb_ftdi *ftdi)
+{
+        ftdi_command_queue_work(ftdi, 0);
+        return;
+}
+
+static void ftdi_elan_command_work(void *data)
+{
+        struct usb_ftdi *ftdi = data;
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else {
+                int retval = ftdi_elan_command_engine(ftdi);
+                if (retval == -ESHUTDOWN) {
+                        ftdi->disconnected += 1;
+                } else if (retval == -ENODEV) {
+                        ftdi->disconnected += 1;
+                } else if (retval)
+                        dev_err(&ftdi->udev->dev, "command error %d\n", retval);
+                ftdi_command_requeue_work(ftdi, msecs_to_jiffies(10));
+                return;
+        }
+}
+
+static void ftdi_elan_kick_respond_queue(struct usb_ftdi *ftdi)
+{
+        ftdi_respond_queue_work(ftdi, 0);
+        return;
+}
+
+static void ftdi_elan_respond_work(void *data)
+{
+        struct usb_ftdi *ftdi = data;
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else {
+                int retval = ftdi_elan_respond_engine(ftdi);
+                if (retval == 0) {
+                } else if (retval == -ESHUTDOWN) {
+                        ftdi->disconnected += 1;
+                } else if (retval == -ENODEV) {
+                        ftdi->disconnected += 1;
+                } else if (retval == -ENODEV) {
+                        ftdi->disconnected += 1;
+                } else if (retval == -EILSEQ) {
+                        ftdi->disconnected += 1;
+                } else {
+                        ftdi->disconnected += 1;
+                        dev_err(&ftdi->udev->dev, "respond error %d\n", retval);
+                }
+                if (ftdi->disconnected > 0) {
+                        ftdi_elan_abandon_completions(ftdi);
+                        ftdi_elan_abandon_targets(ftdi);
+                }
+                ftdi_response_requeue_work(ftdi, msecs_to_jiffies(10));
+                return;
+        }
+}
+
+
+/*
+* the sw_lock is initially held and will be freed
+* after the FTDI has been synchronized
+*
+*/
+static void ftdi_elan_status_work(void *data)
+{
+        struct usb_ftdi *ftdi = data;
+        int work_delay_in_msec = 0;
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else if (ftdi->synchronized == 0) {
+                down(&ftdi->sw_lock);
+                if (ftdi_elan_synchronize(ftdi) == 0) {
+                        ftdi->synchronized = 1;
+                        ftdi_command_queue_work(ftdi, 1);
+                        ftdi_respond_queue_work(ftdi, 1);
+                        up(&ftdi->sw_lock);
+                        work_delay_in_msec = 100;
+                } else {
+                        dev_err(&ftdi->udev->dev, "synchronize failed\n");
+                        up(&ftdi->sw_lock);
+                        work_delay_in_msec = 10 *1000;
+                }
+        } else if (ftdi->stuck_status > 0) {
+                if (ftdi_elan_stuck_waiting(ftdi) == 0) {
+                        ftdi->stuck_status = 0;
+                        ftdi->synchronized = 0;
+                } else if ((ftdi->stuck_status++ % 60) == 1) {
+                        dev_err(&ftdi->udev->dev, "WRONG type of card inserted "
+                                "- please remove\n");
+                } else
+                        dev_err(&ftdi->udev->dev, "WRONG type of card inserted "
+                                "- checked %d times\n", ftdi->stuck_status);
+                work_delay_in_msec = 100;
+        } else if (ftdi->enumerated == 0) {
+                if (ftdi_elan_enumeratePCI(ftdi) == 0) {
+                        ftdi->enumerated = 1;
+                        work_delay_in_msec = 250;
+                } else
+                        work_delay_in_msec = 1000;
+        } else if (ftdi->initialized == 0) {
+                if (ftdi_elan_setupOHCI(ftdi) == 0) {
+                        ftdi->initialized = 1;
+                        work_delay_in_msec = 500;
+                } else {
+                        dev_err(&ftdi->udev->dev, "initialized failed - trying "
+                                "again in 10 seconds\n");
+                        work_delay_in_msec = 10 *1000;
+                }
+        } else if (ftdi->registered == 0) {
+                work_delay_in_msec = 10;
+                if (ftdi_elan_hcd_init(ftdi) == 0) {
+                        ftdi->registered = 1;
+                } else
+                        dev_err(&ftdi->udev->dev, "register failed\n");
+                work_delay_in_msec = 250;
+        } else {
+                if (ftdi_elan_checkingPCI(ftdi) == 0) {
+                        work_delay_in_msec = 250;
+                } else if (ftdi->controlreg & 0x00400000) {
+                        if (ftdi->gone_away > 0) {
+                                dev_err(&ftdi->udev->dev, "PCI device eject con"
+                                        "firmed platform_dev.dev.parent=%p plat"
+                                        "form_dev.dev=%p\n",
+                                        ftdi->platform_dev.dev.parent,
+                                        &ftdi->platform_dev.dev);
+                                platform_device_unregister(&ftdi->platform_dev);
+                                ftdi->platform_dev.dev.parent = NULL;
+                                ftdi->registered = 0;
+                                ftdi->enumerated = 0;
+                                ftdi->card_ejected = 0;
+                                ftdi->initialized = 0;
+                                ftdi->gone_away = 0;
+                        } else
+                                ftdi_elan_flush_targets(ftdi);
+                        work_delay_in_msec = 250;
+                } else {
+                        dev_err(&ftdi->udev->dev, "PCI device has disappeared\n"
+                                );
+                        ftdi_elan_cancel_targets(ftdi);
+                        work_delay_in_msec = 500;
+                        ftdi->enumerated = 0;
+                        ftdi->initialized = 0;
+                }
+        }
+        if (ftdi->disconnected > 0) {
+                ftdi_elan_put_kref(ftdi);
+                return;
+        } else {
+                ftdi_status_requeue_work(ftdi,
+                        msecs_to_jiffies(work_delay_in_msec));
+                return;
+        }
+}
+
+
+/*
+* file_operations for the jtag interface
+*
+* the usage count for the device is incremented on open()
+* and decremented on release()
+*/
+static int ftdi_elan_open(struct inode *inode, struct file *file)
+{
+        int subminor = iminor(inode);
+        struct usb_interface *interface = usb_find_interface(&ftdi_elan_driver,
+                subminor);
+        if (!interface) {
+                printk(KERN_ERR "can't find device for minor %d\n", subminor);
+                return -ENODEV;
+        } else {
+                struct usb_ftdi *ftdi = usb_get_intfdata(interface);
+                if (!ftdi) {
+                        return -ENODEV;
+                } else {
+                        if (down_interruptible(&ftdi->sw_lock)) {
+                                return -EINTR;
+                        } else {
+                                ftdi_elan_get_kref(ftdi);
+                                file->private_data = ftdi;
+                                return 0;
+                        }
+                }
+        }
+}
+
+static int ftdi_elan_release(struct inode *inode, struct file *file)
+{
+        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;
+        if (ftdi == NULL)
+                return -ENODEV;
+        up(&ftdi->sw_lock);        /* decrement the count on our device */
+        ftdi_elan_put_kref(ftdi);
+        return 0;
+}
+
+
+#define FTDI_ELAN_IOC_MAGIC 0xA1
+#define FTDI_ELAN_IOCDEBUG _IOC(_IOC_WRITE, FTDI_ELAN_IOC_MAGIC, 1, 132)
+static int ftdi_elan_ioctl(struct inode *inode, struct file *file,
+        unsigned int cmd, unsigned long arg)
+{
+        switch (cmd) {
+        case FTDI_ELAN_IOCDEBUG:{
+                        char line[132];
+                        int size = strncpy_from_user(line,
+                                (const char __user *)arg, sizeof(line));
+                        if (size < 0) {
+                                return -EINVAL;
+                        } else {
+                                printk(KERN_ERR "TODO: ioctl %s\n", line);
+                                return 0;
+                        }
+                }
+        default:
+                return -EFAULT;
+        }
+}
+
+
+/*
+*
+* blocking bulk reads are used to get data from the device
+*
+*/
+static ssize_t ftdi_elan_read(struct file *file, char __user *buffer,
+                             size_t count, loff_t *ppos)
+{
+        char data[30 *3 + 4];
+        char *d = data;
+        int m = (sizeof(data) - 1) / 3;
+        int bytes_read = 0;
+        int retry_on_empty = 10;
+        int retry_on_timeout = 5;
+        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;
+        if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        }
+        data[0] = 0;
+      have:if (ftdi->bulk_in_left > 0) {
+                if (count-- > 0) {
+                        char *p = ++ftdi->bulk_in_last + ftdi->bulk_in_buffer;
+                        ftdi->bulk_in_left -= 1;
+                        if (bytes_read < m) {
+                                d += sprintf(d, " %02X", 0x000000FF & *p);
+                        } else if (bytes_read > m) {
+                        } else
+                                d += sprintf(d, " ..");
+                        if (copy_to_user(buffer++, p, 1)) {
+                                return -EFAULT;
+                        } else {
+                                bytes_read += 1;
+                                goto have;
+                        }
+                } else
+                        return bytes_read;
+        }
+      more:if (count > 0) {
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(50));
+                if (packet_bytes > 2) {
+                        ftdi->bulk_in_left = packet_bytes - 2;
+                        ftdi->bulk_in_last = 1;
+                        goto have;
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                goto more;
+                        } else if (bytes_read > 0) {
+                                return bytes_read;
+                        } else
+                                return retval;
+                } else if (retval == 0) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else
+                                return bytes_read;
+                } else
+                        return retval;
+        } else
+                return bytes_read;
+}
+
+static void ftdi_elan_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+        struct usb_ftdi *ftdi = (struct usb_ftdi *)urb->context;
+        if (urb->status && !(urb->status == -ENOENT || urb->status ==
+                -ECONNRESET || urb->status == -ESHUTDOWN)) {
+                dev_err(&ftdi->udev->dev, "urb=%p write bulk status received: %"
+                        "d\n", urb, urb->status);
+        }
+        usb_buffer_free(urb->dev, urb->transfer_buffer_length,
+                urb->transfer_buffer, urb->transfer_dma);
+}
+
+static int fill_buffer_with_all_queued_commands(struct usb_ftdi *ftdi,
+        char *buf, int command_size, int total_size)
+{
+        int ed_commands = 0;
+        int b = 0;
+        int I = command_size;
+        int i = ftdi->command_head;
+        while (I-- > 0) {
+                struct u132_command *command = &ftdi->command[COMMAND_MASK &
+                        i++];
+                int F = command->follows;
+                u8 *f = command->buffer;
+                if (command->header & 0x80) {
+                        ed_commands |= 1 << (0x3 & (command->header >> 5));
+                }
+                buf[b++] = command->header;
+                buf[b++] = (command->length >> 0) & 0x00FF;
+                buf[b++] = (command->length >> 8) & 0x00FF;
+                buf[b++] = command->address;
+                buf[b++] = command->width;
+                while (F-- > 0) {
+                        buf[b++] = *f++;
+                }
+        }
+        return ed_commands;
+}
+
+static int ftdi_elan_total_command_size(struct usb_ftdi *ftdi, int command_size)
+{
+        int total_size = 0;
+        int I = command_size;
+        int i = ftdi->command_head;
+        while (I-- > 0) {
+                struct u132_command *command = &ftdi->command[COMMAND_MASK &
+                        i++];
+                total_size += 5 + command->follows;
+        } return total_size;
+}
+
+static int ftdi_elan_command_engine(struct usb_ftdi *ftdi)
+{
+        int retval;
+        char *buf;
+        int ed_commands;
+        int total_size;
+        struct urb *urb;
+        int command_size = ftdi->command_next - ftdi->command_head;
+        if (command_size == 0)
+                return 0;
+        total_size = ftdi_elan_total_command_size(ftdi, command_size);
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                dev_err(&ftdi->udev->dev, "could not get a urb to write %d comm"
+                        "ands totaling %d bytes to the Uxxx\n", command_size,
+                        total_size);
+                return -ENOMEM;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, total_size, GFP_KERNEL,
+                &urb->transfer_dma);
+        if (!buf) {
+                dev_err(&ftdi->udev->dev, "could not get a buffer to write %d c"
+                        "ommands totaling %d bytes to the Uxxx\n", command_size,
+                         total_size);
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        ed_commands = fill_buffer_with_all_queued_commands(ftdi, buf,
+                command_size, total_size);
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, total_size,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        if (ed_commands) {
+                char diag[40 *3 + 4];
+                char *d = diag;
+                int m = total_size;
+                u8 *c = buf;
+                int s = (sizeof(diag) - 1) / 3;
+                diag[0] = 0;
+                while (s-- > 0 && m-- > 0) {
+                        if (s > 0 || m == 0) {
+                                d += sprintf(d, " %02X", *c++);
+                        } else
+                                d += sprintf(d, " ..");
+                }
+        }
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed %d to submit urb %p to write "
+                        "%d commands totaling %d bytes to the Uxxx\n", retval,
+                        urb, command_size, total_size);
+                usb_buffer_free(ftdi->udev, total_size, buf, urb->transfer_dma);
+                usb_free_urb(urb);
+                return retval;
+        }
+        usb_free_urb(urb);        /* release our reference to this urb,
+                the USB core will eventually free it entirely */
+        ftdi->command_head += command_size;
+        ftdi_elan_kick_respond_queue(ftdi);
+        return 0;
+}
+
+static void ftdi_elan_do_callback(struct usb_ftdi *ftdi,
+        struct u132_target *target, u8 *buffer, int length)
+{
+        struct urb *urb = target->urb;
+        int halted = target->halted;
+        int skipped = target->skipped;
+        int actual = target->actual;
+        int non_null = target->non_null;
+        int toggle_bits = target->toggle_bits;
+        int error_count = target->error_count;
+        int condition_code = target->condition_code;
+        int repeat_number = target->repeat_number;
+        void (*callback) (void *, struct urb *, u8 *, int, int, int, int, int,
+                int, int, int, int) = target->callback;
+        target->active -= 1;
+        target->callback = NULL;
+        (*callback) (target->endp, urb, buffer, length, toggle_bits,
+                error_count, condition_code, repeat_number, halted, skipped,
+                actual, non_null);
+}
+
+static char *have_ed_set_response(struct usb_ftdi *ftdi,
+        struct u132_target *target, u16 ed_length, int ed_number, int ed_type,
+        char *b)
+{
+        int payload = (ed_length >> 0) & 0x07FF;
+        down(&ftdi->u132_lock);
+        target->actual = 0;
+        target->non_null = (ed_length >> 15) & 0x0001;
+        target->repeat_number = (ed_length >> 11) & 0x000F;
+        if (ed_type == 0x02) {
+                if (payload == 0 || target->abandoning > 0) {
+                        target->abandoning = 0;
+                        up(&ftdi->u132_lock);
+                        ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                                payload);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        return ftdi->response;
+                } else {
+                        ftdi->expected = 4 + payload;
+                        ftdi->ed_found = 1;
+                        up(&ftdi->u132_lock);
+                        return b;
+                }
+        } else if (ed_type == 0x03) {
+                if (payload == 0 || target->abandoning > 0) {
+                        target->abandoning = 0;
+                        up(&ftdi->u132_lock);
+                        ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                                payload);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        return ftdi->response;
+                } else {
+                        ftdi->expected = 4 + payload;
+                        ftdi->ed_found = 1;
+                        up(&ftdi->u132_lock);
+                        return b;
+                }
+        } else if (ed_type == 0x01) {
+                target->abandoning = 0;
+                up(&ftdi->u132_lock);
+                ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                        payload);
+                ftdi->recieved = 0;
+                ftdi->expected = 4;
+                ftdi->ed_found = 0;
+                return ftdi->response;
+        } else {
+                target->abandoning = 0;
+                up(&ftdi->u132_lock);
+                ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                        payload);
+                ftdi->recieved = 0;
+                ftdi->expected = 4;
+                ftdi->ed_found = 0;
+                return ftdi->response;
+        }
+}
+
+static char *have_ed_get_response(struct usb_ftdi *ftdi,
+        struct u132_target *target, u16 ed_length, int ed_number, int ed_type,
+        char *b)
+{
+        down(&ftdi->u132_lock);
+        target->condition_code = TD_DEVNOTRESP;
+        target->actual = (ed_length >> 0) & 0x01FF;
+        target->non_null = (ed_length >> 15) & 0x0001;
+        target->repeat_number = (ed_length >> 11) & 0x000F;
+        up(&ftdi->u132_lock);
+        if (target->active)
+                ftdi_elan_do_callback(ftdi, target, NULL, 0);
+        target->abandoning = 0;
+        ftdi->recieved = 0;
+        ftdi->expected = 4;
+        ftdi->ed_found = 0;
+        return ftdi->response;
+}
+
+
+/*
+* The engine tries to empty the FTDI fifo
+*
+* all responses found in the fifo data are dispatched thus
+* the response buffer can only ever hold a maximum sized
+* response from the Uxxx.
+*
+*/
+static int ftdi_elan_respond_engine(struct usb_ftdi *ftdi)
+{
+        u8 *b = ftdi->response + ftdi->recieved;
+        int bytes_read = 0;
+        int retry_on_empty = 1;
+        int retry_on_timeout = 3;
+        int empty_packets = 0;
+      read:{
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(500));
+                char diag[30 *3 + 4];
+                char *d = diag;
+                int m = packet_bytes;
+                u8 *c = ftdi->bulk_in_buffer;
+                int s = (sizeof(diag) - 1) / 3;
+                diag[0] = 0;
+                while (s-- > 0 && m-- > 0) {
+                        if (s > 0 || m == 0) {
+                                d += sprintf(d, " %02X", *c++);
+                        } else
+                                d += sprintf(d, " ..");
+                }
+                if (packet_bytes > 2) {
+                        ftdi->bulk_in_left = packet_bytes - 2;
+                        ftdi->bulk_in_last = 1;
+                        goto have;
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT with packe"
+                                        "t_bytes = %d with total %d bytes%s\n",
+                                        packet_bytes, bytes_read, diag);
+                                goto more;
+                        } else if (bytes_read > 0) {
+                                dev_err(&ftdi->udev->dev, "ONLY %d bytes%s\n",
+                                        bytes_read, diag);
+                                return -ENOMEM;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT with packe"
+                                        "t_bytes = %d with total %d bytes%s\n",
+                                        packet_bytes, bytes_read, diag);
+                                return -ENOMEM;
+                        }
+                } else if (retval == -EILSEQ) {
+                        dev_err(&ftdi->udev->dev, "error = %d with packet_bytes"
+                                " = %d with total %d bytes%s\n", retval,
+                                packet_bytes, bytes_read, diag);
+                        return retval;
+                } else if (retval) {
+                        dev_err(&ftdi->udev->dev, "error = %d with packet_bytes"
+                                " = %d with total %d bytes%s\n", retval,
+                                packet_bytes, bytes_read, diag);
+                        return retval;
+                } else if (packet_bytes == 2) {
+                        unsigned char s0 = ftdi->bulk_in_buffer[0];
+                        unsigned char s1 = ftdi->bulk_in_buffer[1];
+                        empty_packets += 1;
+                        if (s0 == 0x31 && s1 == 0x60) {
+                                if (retry_on_empty-- > 0) {
+                                        goto more;
+                                } else
+                                        return 0;
+                        } else if (s0 == 0x31 && s1 == 0x00) {
+                                if (retry_on_empty-- > 0) {
+                                        goto more;
+                                } else
+                                        return 0;
+                        } else {
+                                if (retry_on_empty-- > 0) {
+                                        goto more;
+                                } else
+                                        return 0;
+                        }
+                } else if (packet_bytes == 1) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else
+                                return 0;
+                } else {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else
+                                return 0;
+                }
+        }
+      more:{
+                goto read;
+        }
+      have:if (ftdi->bulk_in_left > 0) {
+                u8 c = ftdi->bulk_in_buffer[++ftdi->bulk_in_last];
+                bytes_read += 1;
+                ftdi->bulk_in_left -= 1;
+                if (ftdi->recieved == 0 && c == 0xFF) {
+                        goto have;
+                } else
+                        *b++ = c;
+                if (++ftdi->recieved < ftdi->expected) {
+                        goto have;
+                } else if (ftdi->ed_found) {
+                        int ed_number = (ftdi->response[0] >> 5) & 0x03;
+                        u16 ed_length = (ftdi->response[2] << 8) |
+                                ftdi->response[1];
+                        struct u132_target *target = &ftdi->target[ed_number];
+                        int payload = (ed_length >> 0) & 0x07FF;
+                        char diag[30 *3 + 4];
+                        char *d = diag;
+                        int m = payload;
+                        u8 *c = 4 + ftdi->response;
+                        int s = (sizeof(diag) - 1) / 3;
+                        diag[0] = 0;
+                        while (s-- > 0 && m-- > 0) {
+                                if (s > 0 || m == 0) {
+                                        d += sprintf(d, " %02X", *c++);
+                                } else
+                                        d += sprintf(d, " ..");
+                        }
+                        ftdi_elan_do_callback(ftdi, target, 4 + ftdi->response,
+                                payload);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        b = ftdi->response;
+                        goto have;
+                } else if (ftdi->expected == 8) {
+                        u8 buscmd;
+                        int respond_head = ftdi->respond_head++;
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & respond_head];
+                        u32 data = ftdi->response[7];
+                        data <<= 8;
+                        data |= ftdi->response[6];
+                        data <<= 8;
+                        data |= ftdi->response[5];
+                        data <<= 8;
+                        data |= ftdi->response[4];
+                        *respond->value = data;
+                        *respond->result = 0;
+                        complete(&respond->wait_completion);
+                        ftdi->recieved = 0;
+                        ftdi->expected = 4;
+                        ftdi->ed_found = 0;
+                        b = ftdi->response;
+                        buscmd = (ftdi->response[0] >> 0) & 0x0F;
+                        if (buscmd == 0x00) {
+                        } else if (buscmd == 0x02) {
+                        } else if (buscmd == 0x06) {
+                        } else if (buscmd == 0x0A) {
+                        } else
+                                dev_err(&ftdi->udev->dev, "Uxxx unknown(%0X) va"
+                                        "lue = %08X\n", buscmd, data);
+                        goto have;
+                } else {
+                        if ((ftdi->response[0] & 0x80) == 0x00) {
+                                ftdi->expected = 8;
+                                goto have;
+                        } else {
+                                int ed_number = (ftdi->response[0] >> 5) & 0x03;
+                                int ed_type = (ftdi->response[0] >> 0) & 0x03;
+                                u16 ed_length = (ftdi->response[2] << 8) |
+                                        ftdi->response[1];
+                                struct u132_target *target = &ftdi->target[
+                                        ed_number];
+                                target->halted = (ftdi->response[0] >> 3) &
+                                        0x01;
+                                target->skipped = (ftdi->response[0] >> 2) &
+                                        0x01;
+                                target->toggle_bits = (ftdi->response[3] >> 6)
+                                        & 0x03;
+                                target->error_count = (ftdi->response[3] >> 4)
+                                        & 0x03;
+                                target->condition_code = (ftdi->response[
+                                        3] >> 0) & 0x0F;
+                                if ((ftdi->response[0] & 0x10) == 0x00) {
+                                        b = have_ed_set_response(ftdi, target,
+                                                ed_length, ed_number, ed_type,
+                                                b);
+                                        goto have;
+                                } else {
+                                        b = have_ed_get_response(ftdi, target,
+                                                ed_length, ed_number, ed_type,
+                                                b);
+                                        goto have;
+                                }
+                        }
+                }
+        } else
+                goto more;
+}
+
+
+/*
+* create a urb, and a buffer for it, and copy the data to the urb
+*
+*/
+static ssize_t ftdi_elan_write(struct file *file,
+                              const char __user *user_buffer, size_t count,
+                              loff_t *ppos)
+{
+        int retval = 0;
+        struct urb *urb;
+        char *buf;
+        char data[30 *3 + 4];
+        char *d = data;
+        const char __user *s = user_buffer;
+        int m = (sizeof(data) - 1) / 3;
+        struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data;
+        if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        }
+        if (count == 0) {
+                goto exit;
+        }
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                retval = -ENOMEM;
+                goto error_1;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, count, GFP_KERNEL,
+                &urb->transfer_dma);
+        if (!buf) {
+                retval = -ENOMEM;
+                goto error_2;
+        }
+        if (copy_from_user(buf, user_buffer, count)) {
+                retval = -EFAULT;
+                goto error_3;
+        }
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, count,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed submitting write urb, error %"
+                        "d\n", retval);
+                goto error_4;
+        }
+        usb_free_urb(urb);
+      exit:;
+        if (count > m) {
+                int I = m - 1;
+                while (I-- > 0) {
+                        d += sprintf(d, " %02X", 0x000000FF & *s++);
+                }
+                d += sprintf(d, " ..");
+        } else {
+                int I = count;
+                while (I-- > 0) {
+                        d += sprintf(d, " %02X", 0x000000FF & *s++);
+                }
+        }
+        return count;
+      error_4: error_3:usb_buffer_free(ftdi->udev, count, buf,
+              urb->transfer_dma);
+      error_2:usb_free_urb(urb);
+      error_1:return retval;
+}
+
+static struct file_operations ftdi_elan_fops = {
+        .owner = THIS_MODULE,
+        .llseek = no_llseek,
+        .ioctl = ftdi_elan_ioctl,
+        .read = ftdi_elan_read,
+        .write = ftdi_elan_write,
+        .open = ftdi_elan_open,
+        .release = ftdi_elan_release,
+};
+
+/*
+* usb class driver info in order to get a minor number from the usb core,
+* and to have the device registered with the driver core
+*/
+static struct usb_class_driver ftdi_elan_jtag_class = {
+        .name = "ftdi-%d-jtag",
+        .fops = &ftdi_elan_fops,
+        .minor_base = USB_FTDI_ELAN_MINOR_BASE,
+};
+
+/*
+* the following definitions are for the
+* ELAN FPGA state machgine processor that
+* lies on the other side of the FTDI chip
+*/
+#define cPCIu132rd 0x0
+#define cPCIu132wr 0x1
+#define cPCIiord 0x2
+#define cPCIiowr 0x3
+#define cPCImemrd 0x6
+#define cPCImemwr 0x7
+#define cPCIcfgrd 0xA
+#define cPCIcfgwr 0xB
+#define cPCInull 0xF
+#define cU132cmd_status 0x0
+#define cU132flash 0x1
+#define cPIDsetup 0x0
+#define cPIDout 0x1
+#define cPIDin 0x2
+#define cPIDinonce 0x3
+#define cCCnoerror 0x0
+#define cCCcrc 0x1
+#define cCCbitstuff 0x2
+#define cCCtoggle 0x3
+#define cCCstall 0x4
+#define cCCnoresp 0x5
+#define cCCbadpid1 0x6
+#define cCCbadpid2 0x7
+#define cCCdataoverrun 0x8
+#define cCCdataunderrun 0x9
+#define cCCbuffoverrun 0xC
+#define cCCbuffunderrun 0xD
+#define cCCnotaccessed 0xF
+static int ftdi_elan_write_reg(struct usb_ftdi *ftdi, u32 data)
+{
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x00 | cPCIu132wr;
+                        command->length = 0x04;
+                        command->address = 0x00;
+                        command->width = 0x00;
+                        command->follows = 4;
+                        command->value = data;
+                        command->buffer = &command->value;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+static int ftdi_elan_write_config(struct usb_ftdi *ftdi, int config_offset,
+        u8 width, u32 data)
+{
+        u8 addressofs = config_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x00 | (cPCIcfgwr & 0x0F);
+                        command->length = 0x04;
+                        command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 4;
+                        command->value = data;
+                        command->buffer = &command->value;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+static int ftdi_elan_write_pcimem(struct usb_ftdi *ftdi, int mem_offset,
+        u8 width, u32 data)
+{
+        u8 addressofs = mem_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x00 | (cPCImemwr & 0x0F);
+                        command->length = 0x04;
+                        command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 4;
+                        command->value = data;
+                        command->buffer = &command->value;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset,
+        u8 width, u32 data)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_write_pcimem(ftdi, mem_offset, width, data);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_write_pcimem);
+static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data)
+{
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                int respond_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                respond_size = ftdi->respond_next - ftdi->respond_head;
+                if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
+                        {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & ftdi->respond_next];
+                        int result = -ENODEV;
+                        respond->result = &result;
+                        respond->header = command->header = 0x00 | cPCIu132rd;
+                        command->length = 0x04;
+                        respond->address = command->address = cU132cmd_status;
+                        command->width = 0x00;
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        respond->value = data;
+                        init_completion(&respond->wait_completion);
+                        ftdi->command_next += 1;
+                        ftdi->respond_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        wait_for_completion(&respond->wait_completion);
+                        return result;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_read_reg(ftdi, data);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_reg);
+static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset,
+        u8 width, u32 *data)
+{
+        u8 addressofs = config_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                int respond_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                respond_size = ftdi->respond_next - ftdi->respond_head;
+                if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
+                        {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & ftdi->respond_next];
+                        int result = -ENODEV;
+                        respond->result = &result;
+                        respond->header = command->header = 0x00 | (cPCIcfgrd &
+                                0x0F);
+                        command->length = 0x04;
+                        respond->address = command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        respond->value = data;
+                        init_completion(&respond->wait_completion);
+                        ftdi->command_next += 1;
+                        ftdi->respond_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        wait_for_completion(&respond->wait_completion);
+                        return result;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+static int ftdi_elan_read_pcimem(struct usb_ftdi *ftdi, int mem_offset,
+        u8 width, u32 *data)
+{
+        u8 addressofs = mem_offset / 4;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                int respond_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                respond_size = ftdi->respond_next - ftdi->respond_head;
+                if (command_size < COMMAND_SIZE && respond_size < RESPOND_SIZE)
+                        {
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        struct u132_respond *respond = &ftdi->respond[
+                                RESPOND_MASK & ftdi->respond_next];
+                        int result = -ENODEV;
+                        respond->result = &result;
+                        respond->header = command->header = 0x00 | (cPCImemrd &
+                                0x0F);
+                        command->length = 0x04;
+                        respond->address = command->address = addressofs;
+                        command->width = 0x00 | (width & 0x0F);
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        respond->value = data;
+                        init_completion(&respond->wait_completion);
+                        ftdi->command_next += 1;
+                        ftdi->respond_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        wait_for_completion(&respond->wait_completion);
+                        return result;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset,
+        u8 width, u32 *data)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else
+                return ftdi_elan_read_pcimem(ftdi, mem_offset, width, data);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_pcimem);
+static int ftdi_elan_edset_setup(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x80 | (ed << 5);
+                        command->length = 0x8007;
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 8;
+                        command->value = 0;
+                        command->buffer = urb->setup_packet;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_setup(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_setup);
+static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        int remaining_length = urb->transfer_buffer_length -
+                                urb->actual_length;
+                        command->header = 0x82 | (ed << 5);
+                        if (remaining_length == 0) {
+                                command->length = 0x0000;
+                        } else if (remaining_length > 1024) {
+                                command->length = 0x8000 | 1023;
+                        } else
+                                command->length = 0x8000 | (remaining_length -
+                                        1);
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_input(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_input(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_input);
+static int ftdi_elan_edset_empty(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x81 | (ed << 5);
+                        command->length = 0x0000;
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_empty(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_empty(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_empty);
+static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        u8 *b;
+                        u16 urb_size;
+                        int i = 0;
+                        char data[30 *3 + 4];
+                        char *d = data;
+                        int m = (sizeof(data) - 1) / 3;
+                        int l = 0;
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x81 | (ed << 5);
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = min(1024,
+                                urb->transfer_buffer_length -
+                                urb->actual_length);
+                        command->value = 0;
+                        command->buffer = urb->transfer_buffer +
+                                urb->actual_length;
+                        command->length = 0x8000 | (command->follows - 1);
+                        b = command->buffer;
+                        urb_size = command->follows;
+                        data[0] = 0;
+                        while (urb_size-- > 0) {
+                                if (i > m) {
+                                } else if (i++ < m) {
+                                        int w = sprintf(d, " %02X", *b++);
+                                        d += w;
+                                        l += w;
+                                } else
+                                        d += sprintf(d, " ..");
+                        }
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_output(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_output(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_output);
+static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        u8 ed = ed_number - 1;
+      wait:if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                int command_size;
+                down(&ftdi->u132_lock);
+                command_size = ftdi->command_next - ftdi->command_head;
+                if (command_size < COMMAND_SIZE) {
+                        int remaining_length = urb->transfer_buffer_length -
+                                urb->actual_length;
+                        struct u132_target *target = &ftdi->target[ed];
+                        struct u132_command *command = &ftdi->command[
+                                COMMAND_MASK & ftdi->command_next];
+                        command->header = 0x83 | (ed << 5);
+                        if (remaining_length == 0) {
+                                command->length = 0x0000;
+                        } else if (remaining_length > 1024) {
+                                command->length = 0x8000 | 1023;
+                        } else
+                                command->length = 0x8000 | (remaining_length -
+                                        1);
+                        command->address = (toggle_bits << 6) | (ep_number << 2)
+                                | (address << 0);
+                        command->width = usb_maxpacket(urb->dev, urb->pipe,
+                                usb_pipeout(urb->pipe));
+                        command->follows = 0;
+                        command->value = 0;
+                        command->buffer = NULL;
+                        target->callback = callback;
+                        target->endp = endp;
+                        target->urb = urb;
+                        target->active = 1;
+                        ftdi->command_next += 1;
+                        ftdi_elan_kick_command_queue(ftdi);
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        up(&ftdi->u132_lock);
+                        msleep(100);
+                        goto wait;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_single(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null))
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_single(ftdi, ed_number, endp, urb, address,
+                ep_number, toggle_bits, callback);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_single);
+static int ftdi_elan_edset_flush(struct usb_ftdi *ftdi, u8 ed_number,
+        void *endp)
+{
+        u8 ed = ed_number - 1;
+        if (ftdi->disconnected > 0) {
+                return -ENODEV;
+        } else if (ftdi->initialized == 0) {
+                return -ENODEV;
+        } else {
+                struct u132_target *target = &ftdi->target[ed];
+                down(&ftdi->u132_lock);
+                if (target->abandoning > 0) {
+                        up(&ftdi->u132_lock);
+                        return 0;
+                } else {
+                        target->abandoning = 1;
+                      wait_1:if (target->active == 1) {
+                                int command_size = ftdi->command_next -
+                                        ftdi->command_head;
+                                if (command_size < COMMAND_SIZE) {
+                                        struct u132_command *command =
+                                                &ftdi->command[COMMAND_MASK &
+                                                ftdi->command_next];
+                                        command->header = 0x80 | (ed << 5) |
+                                                0x4;
+                                        command->length = 0x00;
+                                        command->address = 0x00;
+                                        command->width = 0x00;
+                                        command->follows = 0;
+                                        command->value = 0;
+                                        command->buffer = &command->value;
+                                        ftdi->command_next += 1;
+                                        ftdi_elan_kick_command_queue(ftdi);
+                                } else {
+                                        up(&ftdi->u132_lock);
+                                        msleep(100);
+                                        down(&ftdi->u132_lock);
+                                        goto wait_1;
+                                }
+                        }
+                        up(&ftdi->u132_lock);
+                        return 0;
+                }
+        }
+}
+
+int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
+        void *endp)
+{
+        struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
+        return ftdi_elan_edset_flush(ftdi, ed_number, endp);
+}
+
+
+EXPORT_SYMBOL_GPL(usb_ftdi_elan_edset_flush);
+static int ftdi_elan_flush_input_fifo(struct usb_ftdi *ftdi)
+{
+        int retry_on_empty = 10;
+        int retry_on_timeout = 5;
+        int retry_on_status = 20;
+      more:{
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(100));
+                if (packet_bytes > 2) {
+                        char diag[30 *3 + 4];
+                        char *d = diag;
+                        int m = (sizeof(diag) - 1) / 3;
+                        char *b = ftdi->bulk_in_buffer;
+                        int bytes_read = 0;
+                        diag[0] = 0;
+                        while (packet_bytes-- > 0) {
+                                char c = *b++;
+                                if (bytes_read < m) {
+                                        d += sprintf(d, " %02X",
+                                                0x000000FF & c);
+                                } else if (bytes_read > m) {
+                                } else
+                                        d += sprintf(d, " ..");
+                                bytes_read += 1;
+                                continue;
+                        }
+                        goto more;
+                } else if (packet_bytes > 1) {
+                        char s1 = ftdi->bulk_in_buffer[0];
+                        char s2 = ftdi->bulk_in_buffer[1];
+                        if (s1 == 0x31 && s2 == 0x60) {
+                                return 0;
+                        } else if (retry_on_status-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "STATUS ERROR retry l"
+                                        "imit reached\n");
+                                return -EFAULT;
+                        }
+                } else if (packet_bytes > 0) {
+                        char b1 = ftdi->bulk_in_buffer[0];
+                        dev_err(&ftdi->udev->dev, "only one byte flushed from F"
+                                "TDI = %02X\n", b1);
+                        if (retry_on_status-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "STATUS ERROR retry l"
+                                        "imit reached\n");
+                                return -EFAULT;
+                        }
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT retry limi"
+                                        "t reached\n");
+                                return -ENOMEM;
+                        }
+                } else if (retval == 0) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "empty packet retry l"
+                                        "imit reached\n");
+                                return -ENOMEM;
+                        }
+                } else {
+                        dev_err(&ftdi->udev->dev, "error = %d\n", retval);
+                        return retval;
+                }
+        }
+        return -1;
+}
+
+
+/*
+* send the long flush sequence
+*
+*/
+static int ftdi_elan_synchronize_flush(struct usb_ftdi *ftdi)
+{
+        int retval;
+        struct urb *urb;
+        char *buf;
+        int I = 257;
+        int i = 0;
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                dev_err(&ftdi->udev->dev, "could not alloc a urb for flush sequ"
+                        "ence\n");
+                return -ENOMEM;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma);
+        if (!buf) {
+                dev_err(&ftdi->udev->dev, "could not get a buffer for flush seq"
+                        "uence\n");
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        while (I-- > 0)
+                buf[i++] = 0x55;
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, i,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed to submit urb containing the "
+                        "flush sequence\n");
+                usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma);
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        usb_free_urb(urb);
+        return 0;
+}
+
+
+/*
+* send the reset sequence
+*
+*/
+static int ftdi_elan_synchronize_reset(struct usb_ftdi *ftdi)
+{
+        int retval;
+        struct urb *urb;
+        char *buf;
+        int I = 4;
+        int i = 0;
+        urb = usb_alloc_urb(0, GFP_KERNEL);
+        if (!urb) {
+                dev_err(&ftdi->udev->dev, "could not get a urb for the reset se"
+                        "quence\n");
+                return -ENOMEM;
+        }
+        buf = usb_buffer_alloc(ftdi->udev, I, GFP_KERNEL, &urb->transfer_dma);
+        if (!buf) {
+                dev_err(&ftdi->udev->dev, "could not get a buffer for the reset"
+                        " sequence\n");
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        buf[i++] = 0x55;
+        buf[i++] = 0xAA;
+        buf[i++] = 0x5A;
+        buf[i++] = 0xA5;
+        usb_fill_bulk_urb(urb, ftdi->udev, usb_sndbulkpipe(ftdi->udev,
+                ftdi->bulk_out_endpointAddr), buf, i,
+                ftdi_elan_write_bulk_callback, ftdi);
+        urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+        retval = usb_submit_urb(urb, GFP_KERNEL);
+        if (retval) {
+                dev_err(&ftdi->udev->dev, "failed to submit urb containing the "
+                        "reset sequence\n");
+                usb_buffer_free(ftdi->udev, i, buf, urb->transfer_dma);
+                usb_free_urb(urb);
+                return -ENOMEM;
+        }
+        usb_free_urb(urb);
+        return 0;
+}
+
+static int ftdi_elan_synchronize(struct usb_ftdi *ftdi)
+{
+        int retval;
+        int long_stop = 10;
+        int retry_on_timeout = 5;
+        int retry_on_empty = 10;
+        int err_count = 0;
+        retval = ftdi_elan_flush_input_fifo(ftdi);
+        if (retval)
+                return retval;
+        ftdi->bulk_in_left = 0;
+        ftdi->bulk_in_last = -1;
+        while (long_stop-- > 0) {
+                int read_stop;
+                int read_stuck;
+                retval = ftdi_elan_synchronize_flush(ftdi);
+                if (retval)
+                        return retval;
+                retval = ftdi_elan_flush_input_fifo(ftdi);
+                if (retval)
+                        return retval;
+              reset:retval = ftdi_elan_synchronize_reset(ftdi);
+                if (retval)
+                        return retval;
+                read_stop = 100;
+                read_stuck = 10;
+              read:{
+                        int packet_bytes = 0;
+                        retval = usb_bulk_msg(ftdi->udev,
+                                usb_rcvbulkpipe(ftdi->udev,
+                                ftdi->bulk_in_endpointAddr),
+                                ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                                &packet_bytes, msecs_to_jiffies(500));
+                        if (packet_bytes > 2) {
+                                char diag[30 *3 + 4];
+                                char *d = diag;
+                                int m = (sizeof(diag) - 1) / 3;
+                                char *b = ftdi->bulk_in_buffer;
+                                int bytes_read = 0;
+                                unsigned char c = 0;
+                                diag[0] = 0;
+                                while (packet_bytes-- > 0) {
+                                        c = *b++;
+                                        if (bytes_read < m) {
+                                                d += sprintf(d, " %02X", c);
+                                        } else if (bytes_read > m) {
+                                        } else
+                                                d += sprintf(d, " ..");
+                                        bytes_read += 1;
+                                        continue;
+                                }
+                                if (c == 0x7E) {
+                                        return 0;
+                                } else {
+                                        if (c == 0x55) {
+                                                goto read;
+                                        } else if (read_stop-- > 0) {
+                                                goto read;
+                                        } else {
+                                                dev_err(&ftdi->udev->dev, "retr"
+                                                        "y limit reached\n");
+                                                continue;
+                                        }
+                                }
+                        } else if (packet_bytes > 1) {
+                                unsigned char s1 = ftdi->bulk_in_buffer[0];
+                                unsigned char s2 = ftdi->bulk_in_buffer[1];
+                                if (s1 == 0x31 && s2 == 0x00) {
+                                        if (read_stuck-- > 0) {
+                                                goto read;
+                                        } else
+                                                goto reset;
+                                } else if (s1 == 0x31 && s2 == 0x60) {
+                                        if (read_stop-- > 0) {
+                                                goto read;
+                                        } else {
+                                                dev_err(&ftdi->udev->dev, "retr"
+                                                        "y limit reached\n");
+                                                continue;
+                                        }
+                                } else {
+                                        if (read_stop-- > 0) {
+                                                goto read;
+                                        } else {
+                                                dev_err(&ftdi->udev->dev, "retr"
+                                                        "y limit reached\n");
+                                                continue;
+                                        }
+                                }
+                        } else if (packet_bytes > 0) {
+                                if (read_stop-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "retry limit "
+                                                "reached\n");
+                                        continue;
+                                }
+                        } else if (retval == -ETIMEDOUT) {
+                                if (retry_on_timeout-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "TIMED OUT re"
+                                                "try limit reached\n");
+                                        continue;
+                                }
+                        } else if (retval == 0) {
+                                if (retry_on_empty-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "empty packet"
+                                                " retry limit reached\n");
+                                        continue;
+                                }
+                        } else {
+                                err_count += 1;
+                                dev_err(&ftdi->udev->dev, "error = %d\n",
+                                        retval);
+                                if (read_stop-- > 0) {
+                                        goto read;
+                                } else {
+                                        dev_err(&ftdi->udev->dev, "retry limit "
+                                                "reached\n");
+                                        continue;
+                                }
+                        }
+                }
+        }
+        dev_err(&ftdi->udev->dev, "failed to synchronize\n");
+        return -EFAULT;
+}
+
+static int ftdi_elan_stuck_waiting(struct usb_ftdi *ftdi)
+{
+        int retry_on_empty = 10;
+        int retry_on_timeout = 5;
+        int retry_on_status = 50;
+      more:{
+                int packet_bytes = 0;
+                int retval = usb_bulk_msg(ftdi->udev,
+                        usb_rcvbulkpipe(ftdi->udev, ftdi->bulk_in_endpointAddr),
+                         ftdi->bulk_in_buffer, ftdi->bulk_in_size,
+                        &packet_bytes, msecs_to_jiffies(1000));
+                if (packet_bytes > 2) {
+                        char diag[30 *3 + 4];
+                        char *d = diag;
+                        int m = (sizeof(diag) - 1) / 3;
+                        char *b = ftdi->bulk_in_buffer;
+                        int bytes_read = 0;
+                        diag[0] = 0;
+                        while (packet_bytes-- > 0) {
+                                char c = *b++;
+                                if (bytes_read < m) {
+                                        d += sprintf(d, " %02X",
+                                                0x000000FF & c);
+                                } else if (bytes_read > m) {
+                                } else
+                                        d += sprintf(d, " ..");
+                                bytes_read += 1;
+                                continue;
+                        }
+                        goto more;
+                } else if (packet_bytes > 1) {
+                        char s1 = ftdi->bulk_in_buffer[0];
+                        char s2 = ftdi->bulk_in_buffer[1];
+                        if (s1 == 0x31 && s2 == 0x60) {
+                                return 0;
+                        } else if (retry_on_status-- > 0) {
+                                msleep(5);
+                                goto more;
+                        } else
+                                return -EFAULT;
+                } else if (packet_bytes > 0) {
+                        char b1 = ftdi->bulk_in_buffer[0];
+                        dev_err(&ftdi->udev->dev, "only one byte flushed from F"
+                                "TDI = %02X\n", b1);
+                        if (retry_on_status-- > 0) {
+                                msleep(5);
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "STATUS ERROR retry l"
+                                        "imit reached\n");
+                                return -EFAULT;
+                        }
+                } else if (retval == -ETIMEDOUT) {
+                        if (retry_on_timeout-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "TIMED OUT retry limi"
+                                        "t reached\n");
+                                return -ENOMEM;
+                        }
+                } else if (retval == 0) {
+                        if (retry_on_empty-- > 0) {
+                                goto more;
+                        } else {
+                                dev_err(&ftdi->udev->dev, "empty packet retry l"
+                                        "imit reached\n");
+                                return -ENOMEM;
+                        }
+                } else {
+                        dev_err(&ftdi->udev->dev, "error = %d\n", retval);
+                        return -ENOMEM;
+                }
+        }
+        return -1;
+}
+
+static int ftdi_elan_checkingPCI(struct usb_ftdi *ftdi)
+{
+        int UxxxStatus = ftdi_elan_read_reg(ftdi, &ftdi->controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        if (ftdi->controlreg & 0x00400000) {
+                if (ftdi->card_ejected) {
+                } else {
+                        ftdi->card_ejected = 1;
+                        dev_err(&ftdi->udev->dev, "CARD EJECTED - controlreg = "
+                                "%08X\n", ftdi->controlreg);
+                }
+                return -ENODEV;
+        } else {
+                u8 fn = ftdi->function - 1;
+                int activePCIfn = fn << 8;
+                u32 pcidata;
+                u32 pciVID;
+                u32 pciPID;
+                int reg = 0;
+                UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                        &pcidata);
+                if (UxxxStatus)
+                        return UxxxStatus;
+                pciVID = pcidata & 0xFFFF;
+                pciPID = (pcidata >> 16) & 0xFFFF;
+                if (pciVID == ftdi->platform_data.vendor && pciPID ==
+                        ftdi->platform_data.device) {
+                        return 0;
+                } else {
+                        dev_err(&ftdi->udev->dev, "vendor=%04X pciVID=%04X devi"
+                                "ce=%04X pciPID=%04X\n",
+                                ftdi->platform_data.vendor, pciVID,
+                                ftdi->platform_data.device, pciPID);
+                        return -ENODEV;
+                }
+        }
+}
+
+static int ftdi_elan_enumeratePCI(struct usb_ftdi *ftdi)
+{
+        u32 latence_timer;
+        u32 controlreg;
+        int UxxxStatus;
+        u32 pcidata;
+        int reg = 0;
+        int foundOHCI = 0;
+        u8 fn;
+        int activePCIfn = 0;
+        u32 pciVID = 0;
+        u32 pciPID = 0;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000000L);
+        if (UxxxStatus)
+                return UxxxStatus;
+        msleep(750);
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x100);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x00000200L | 0x500);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020CL | 0x000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020DL | 0x000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        msleep(250);
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000020FL | 0x000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x800);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_reg(ftdi, &controlreg);
+        if (UxxxStatus)
+                return UxxxStatus;
+        msleep(1000);
+        for (fn = 0; (fn < 4) && (!foundOHCI); fn++) {
+                activePCIfn = fn << 8;
+                ftdi->function = fn + 1;
+                UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                        &pcidata);
+                if (UxxxStatus)
+                        return UxxxStatus;
+                pciVID = pcidata & 0xFFFF;
+                pciPID = (pcidata >> 16) & 0xFFFF;
+                if ((pciVID == 0x1045) && (pciPID == 0xc861)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x1033) && (pciPID == 0x0035)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x10b9) && (pciPID == 0x5237)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x11c1) && (pciPID == 0x5802)) {
+                        foundOHCI = 1;
+                } else if ((pciVID == 0x11AB) && (pciPID == 0x1FA6)) {
+                }
+        }
+        if (foundOHCI == 0) {
+                return -ENXIO;
+        }
+        ftdi->platform_data.vendor = pciVID;
+        ftdi->platform_data.device = pciPID;
+        UxxxStatus = ftdi_elan_write_reg(ftdi, 0x0000025FL | 0x2800);
+        if (UxxxStatus)
+                return UxxxStatus;
+        reg = 16;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
+                0xFFFFFFFF);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0,
+                0xF0000000);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        reg = 12;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &latence_timer);
+        if (UxxxStatus)
+                return UxxxStatus;
+        latence_timer &= 0xFFFF00FF;
+        latence_timer |= 0x00001600;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
+                latence_timer);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        reg = 4;
+        UxxxStatus = ftdi_elan_write_config(ftdi, activePCIfn | reg, 0x00,
+                0x06);
+        if (UxxxStatus)
+                return UxxxStatus;
+        UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
+                &pcidata);
+        if (UxxxStatus)
+                return UxxxStatus;
+        return 0;
+}
+
+static int ftdi_elan_setupOHCI(struct usb_ftdi *ftdi)
+{
+        u32 pcidata;
+        int U132Status;
+        int reg;
+        int reset_repeat = 0;
+      do_reset:reg = 8;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x01);
+        if (U132Status)
+                return U132Status;
+      reset_check:{
+                U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+                if (U132Status)
+                        return U132Status;
+                if (pcidata & 1) {
+                        msleep(500);
+                        if (reset_repeat++ > 100) {
+                                reset_repeat = 0;
+                                goto do_reset;
+                        } else
+                                goto reset_check;
+                }
+        }
+        goto dump_regs;
+        msleep(500);
+        reg = 0x28;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x11000000);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x40;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x34;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x2edf2edf);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 4;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0xA0);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        msleep(250);
+        reg = 8;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x0e, 0x04);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x28;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 8;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x48;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x00001200);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x58;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x34;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x28002edf);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        msleep(100);
+        reg = 0x50;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10000);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+      power_check:U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        if (!(pcidata & 1)) {
+                msleep(500);
+                goto power_check;
+        }
+        msleep(3000);
+        reg = 0x54;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x58;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x54;
+        U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x10);
+        if (U132Status)
+                return U132Status;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        msleep(750);
+        reg = 0x54;
+        if (0) {
+                U132Status = ftdi_elan_write_pcimem(ftdi, reg, 0x00, 0x02);
+                if (U132Status)
+                        return U132Status;
+        }
+        if (0) {
+                U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+                if (U132Status)
+                        return U132Status;
+        }
+        reg = 0x54;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+        reg = 0x58;
+        U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+        if (U132Status)
+                return U132Status;
+      dump_regs:for (reg = 0; reg <= 0x54; reg += 4) {
+                U132Status = ftdi_elan_read_pcimem(ftdi, reg, 0, &pcidata);
+                if (U132Status)
+                        return U132Status;
+        }
+        return 0;
+}
+
+
+/*
+* we use only the first bulk-in and bulk-out endpoints
+*/
+static int ftdi_elan_probe(struct usb_interface *interface,
+        const struct usb_device_id *id)
+{
+        struct usb_host_interface *iface_desc;
+        struct usb_endpoint_descriptor *endpoint;
+        size_t buffer_size;
+        int i;
+        int retval = -ENOMEM;
+        struct usb_ftdi *ftdi = kmalloc(sizeof(struct usb_ftdi), GFP_KERNEL);
+        if (ftdi == NULL) {
+                printk(KERN_ERR "Out of memory\n");
+                return -ENOMEM;
+        }
+        memset(ftdi, 0x00, sizeof(struct usb_ftdi));
+        down(&ftdi_module_lock);
+        list_add_tail(&ftdi->ftdi_list, &ftdi_static_list);
+        ftdi->sequence_num = ++ftdi_instances;
+        up(&ftdi_module_lock);
+        ftdi_elan_init_kref(ftdi);
+        init_MUTEX(&ftdi->sw_lock);
+        ftdi->udev = usb_get_dev(interface_to_usbdev(interface));
+        ftdi->interface = interface;
+        init_MUTEX(&ftdi->u132_lock);
+        ftdi->expected = 4;
+        iface_desc = interface->cur_altsetting;
+        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+                endpoint = &iface_desc->endpoint[i].desc;
+                if (!ftdi->bulk_in_endpointAddr &&
+                        ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+                        == USB_DIR_IN) && ((endpoint->bmAttributes &
+                        USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
+                        {
+                        buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
+                        ftdi->bulk_in_size = buffer_size;
+                        ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress;
+                        ftdi->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
+                        if (!ftdi->bulk_in_buffer) {
+                                dev_err(&ftdi->udev->dev, "Could not allocate b"
+                                        "ulk_in_buffer\n");
+                                retval = -ENOMEM;
+                                goto error;
+                        }
+                }
+                if (!ftdi->bulk_out_endpointAddr &&
+                        ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+                        == USB_DIR_OUT) && ((endpoint->bmAttributes &
+                        USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
+                        {
+                        ftdi->bulk_out_endpointAddr =
+                                endpoint->bEndpointAddress;
+                }
+        }
+        if (!(ftdi->bulk_in_endpointAddr && ftdi->bulk_out_endpointAddr)) {
+                dev_err(&ftdi->udev->dev, "Could not find both bulk-in and bulk"
+                        "-out endpoints\n");
+                retval = -ENODEV;
+                goto error;
+        }
+        dev_info(&ftdi->udev->dev, "interface %d has I=%02X O=%02X\n",
+                iface_desc->desc.bInterfaceNumber, ftdi->bulk_in_endpointAddr,
+                ftdi->bulk_out_endpointAddr);
+        usb_set_intfdata(interface, ftdi);
+        if (iface_desc->desc.bInterfaceNumber == 0 &&
+                ftdi->bulk_in_endpointAddr == 0x81 &&
+                ftdi->bulk_out_endpointAddr == 0x02) {
+                retval = usb_register_dev(interface, &ftdi_elan_jtag_class);
+                if (retval) {
+                        dev_err(&ftdi->udev->dev, "Not able to get a minor for "
+                                "this device.\n");
+                        usb_set_intfdata(interface, NULL);
+                        retval = -ENOMEM;
+                        goto error;
+                } else {
+                        ftdi->class = &ftdi_elan_jtag_class;
+                        dev_info(&ftdi->udev->dev, "USB FDTI=%p JTAG interface "
+                                "%d now attached to ftdi%d\n", ftdi,
+                                iface_desc->desc.bInterfaceNumber,
+                                interface->minor);
+                        return 0;
+                }
+        } else if (iface_desc->desc.bInterfaceNumber == 1 &&
+                ftdi->bulk_in_endpointAddr == 0x83 &&
+                ftdi->bulk_out_endpointAddr == 0x04) {
+                ftdi->class = NULL;
+                dev_info(&ftdi->udev->dev, "USB FDTI=%p ELAN interface %d now a"
+                        "ctivated\n", ftdi, iface_desc->desc.bInterfaceNumber);
+                INIT_WORK(&ftdi->status_work, ftdi_elan_status_work,
+                        (void *)ftdi);
+                INIT_WORK(&ftdi->command_work, ftdi_elan_command_work,
+                        (void *)ftdi);
+                INIT_WORK(&ftdi->respond_work, ftdi_elan_respond_work,
+                        (void *)ftdi);
+                ftdi_status_queue_work(ftdi, msecs_to_jiffies(3 *1000));
+                return 0;
+        } else {
+                dev_err(&ftdi->udev->dev,
+                        "Could not find ELAN's U132 device\n");
+                retval = -ENODEV;
+                goto error;
+        }
+      error:if (ftdi) {
+                ftdi_elan_put_kref(ftdi);
+        }
+        return retval;
+}
+
+static void ftdi_elan_disconnect(struct usb_interface *interface)
+{
+        struct usb_ftdi *ftdi = usb_get_intfdata(interface);
+        ftdi->disconnected += 1;
+        if (ftdi->class) {
+                int minor = interface->minor;
+                struct usb_class_driver *class = ftdi->class;
+                usb_set_intfdata(interface, NULL);
+                usb_deregister_dev(interface, class);
+                dev_info(&ftdi->udev->dev, "USB FTDI U132 jtag interface on min"
+                        "or %d now disconnected\n", minor);
+        } else {
+                ftdi_status_cancel_work(ftdi);
+                ftdi_command_cancel_work(ftdi);
+                ftdi_response_cancel_work(ftdi);
+                ftdi_elan_abandon_completions(ftdi);
+                ftdi_elan_abandon_targets(ftdi);
+                if (ftdi->registered) {
+                        platform_device_unregister(&ftdi->platform_dev);
+                        ftdi->synchronized = 0;
+                        ftdi->enumerated = 0;
+                        ftdi->registered = 0;
+                }
+                flush_workqueue(status_queue);
+                flush_workqueue(command_queue);
+                flush_workqueue(respond_queue);
+                ftdi->disconnected += 1;
+                usb_set_intfdata(interface, NULL);
+                dev_info(&ftdi->udev->dev, "USB FTDI U132 host controller inter"
+                        "face now disconnected\n");
+        }
+        ftdi_elan_put_kref(ftdi);
+}
+
+static struct usb_driver ftdi_elan_driver = {
+        .name = "ftdi-elan",
+        .probe = ftdi_elan_probe,
+        .disconnect = ftdi_elan_disconnect,
+        .id_table = ftdi_elan_table,
+};
+static int __init ftdi_elan_init(void)
+{
+        int result;
+        printk(KERN_INFO "driver %s built at %s on %s\n", ftdi_elan_driver.name,
+                 __TIME__, __DATE__);
+        init_MUTEX(&ftdi_module_lock);
+        INIT_LIST_HEAD(&ftdi_static_list);
+        status_queue = create_singlethread_workqueue("ftdi-status-control");
+        command_queue = create_singlethread_workqueue("ftdi-command-engine");
+        respond_queue = create_singlethread_workqueue("ftdi-respond-engine");
+        result = usb_register(&ftdi_elan_driver);
+        if (result)
+                printk(KERN_ERR "usb_register failed. Error number %d\n",
+                        result);
+        return result;
+}
+
+static void __exit ftdi_elan_exit(void)
+{
+        struct usb_ftdi *ftdi;
+        struct usb_ftdi *temp;
+        usb_deregister(&ftdi_elan_driver);
+        printk(KERN_INFO "ftdi_u132 driver deregistered\n");
+        list_for_each_entry_safe(ftdi, temp, &ftdi_static_list, ftdi_list) {
+                ftdi_status_cancel_work(ftdi);
+                ftdi_command_cancel_work(ftdi);
+                ftdi_response_cancel_work(ftdi);
+        } flush_workqueue(status_queue);
+        destroy_workqueue(status_queue);
+        status_queue = NULL;
+        flush_workqueue(command_queue);
+        destroy_workqueue(command_queue);
+        command_queue = NULL;
+        flush_workqueue(respond_queue);
+        destroy_workqueue(respond_queue);
+        respond_queue = NULL;
+}
+
+
+module_init(ftdi_elan_init);
+module_exit(ftdi_elan_exit);
index fcd69c52aea93a9f2acb1736672929ee7e70c2e9..8e6e195a22ba326229de458591eec586a1e4df9a 100644 (file)
@@ -98,7 +98,7 @@ static int idmouse_probe(struct usb_interface *interface,
 static void idmouse_disconnect(struct usb_interface *interface);
 
 /* file operation pointers */
-static struct file_operations idmouse_fops = {
+static const struct file_operations idmouse_fops = {
        .owner = THIS_MODULE,
        .read = idmouse_read,
        .open = idmouse_open,
index f30ab1fbb3c8c5f119edf1ac66dd1e3d31341bfe..10b640339d8dc6e832a1c20cabdb272ebe0c323a 100644 (file)
@@ -589,7 +589,7 @@ exit:
 }
 
 /* file operations needed when we register this driver */
-static struct file_operations ld_usb_fops = {
+static const struct file_operations ld_usb_fops = {
        .owner =        THIS_MODULE,
        .read  =        ld_usb_read,
        .write =        ld_usb_write,
@@ -657,15 +657,11 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;
 
-               if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+               if (usb_endpoint_is_int_in(endpoint))
                        dev->interrupt_in_endpoint = endpoint;
-               }
 
-               if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
+               if (usb_endpoint_is_int_out(endpoint))
                        dev->interrupt_out_endpoint = endpoint;
-               }
        }
        if (dev->interrupt_in_endpoint == NULL) {
                dev_err(&intf->dev, "Interrupt in endpoint not found\n");
index 7699d970e680d783bbb83c6a06280c9552bf2fcb..77c36e63c7bff169c405357bbec5270565ab80bb 100644 (file)
@@ -259,7 +259,7 @@ static void tower_disconnect        (struct usb_interface *interface);
 static DEFINE_MUTEX (disconnect_mutex);
 
 /* file operations needed when we register this driver */
-static struct file_operations tower_fops = {
+static const struct file_operations tower_fops = {
        .owner =        THIS_MODULE,
        .read  =        tower_read,
        .write =        tower_write,
diff --git a/drivers/usb/misc/phidget.c b/drivers/usb/misc/phidget.c
new file mode 100644 (file)
index 0000000..735ed33
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * USB Phidgets class
+ *
+ * Copyright (C) 2006  Sean Young <sean@mess.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/device.h>
+
+struct class *phidget_class;
+
+static int __init init_phidget(void)
+{
+       phidget_class = class_create(THIS_MODULE, "phidget");
+
+       if (IS_ERR(phidget_class))
+               return PTR_ERR(phidget_class);
+
+       return 0;
+}
+
+static void __exit cleanup_phidget(void)
+{
+       class_destroy(phidget_class);
+}
+
+EXPORT_SYMBOL_GPL(phidget_class);
+
+module_init(init_phidget);
+module_exit(cleanup_phidget);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sean Young <sean@mess.org>");
+MODULE_DESCRIPTION("Container module for phidget class");
+
diff --git a/drivers/usb/misc/phidget.h b/drivers/usb/misc/phidget.h
new file mode 100644 (file)
index 0000000..c401190
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * USB Phidgets class
+ *
+ * Copyright (C) 2006  Sean Young <sean@mess.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+extern struct class *phidget_class;
index bfbbbfbb92bcca4ef3b56fe8aea5241ef057ca7b..9a8d137d39f91d75dd9273ba16ef13adfbf6ffa6 100644 (file)
@@ -20,6 +20,8 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 
+#include "phidget.h"
+
 #define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
 #define DRIVER_DESC "USB PhidgetInterfaceKit Driver"
 
@@ -57,11 +59,15 @@ ifkit(8, 8, 4, 0);
 ifkit(0, 8, 8, 1);
 ifkit(0, 16, 16, 0);
 
+static unsigned long device_no;
+
 struct interfacekit {
        struct usb_device *udev;
        struct usb_interface *intf;
        struct driver_interfacekit *ifkit;
+       struct device *dev;
        unsigned long outputs;
+       int dev_no;
        u8 inputs[MAX_INTERFACES];
        u16 sensors[MAX_INTERFACES];
        u8 lcd_files_on;
@@ -180,21 +186,24 @@ exit:
 }
 
 #define set_lcd_line(number)   \
-static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)     \
-{                                                                                      \
-       struct usb_interface *intf = to_usb_interface(dev);                             \
-       struct interfacekit *kit = usb_get_intfdata(intf);                              \
-       change_string(kit, buf, number - 1);                                            \
-       return count;                                                                   \
-}                                                                                      \
-static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number);
+static ssize_t lcd_line_##number(struct device *dev,                   \
+                                       struct device_attribute *attr,  \
+                                       const char *buf, size_t count)  \
+{                                                                      \
+       struct interfacekit *kit = dev_get_drvdata(dev);                \
+       change_string(kit, buf, number - 1);                            \
+       return count;                                                   \
+}
+
+#define lcd_line_attr(number)                                          \
+       __ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number)
+
 set_lcd_line(1);
 set_lcd_line(2);
 
 static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct usb_interface *intf = to_usb_interface(dev);
-       struct interfacekit *kit = usb_get_intfdata(intf);
+       struct interfacekit *kit = dev_get_drvdata(dev);
        int enabled;
        unsigned char *buffer;
        int retval = -ENOMEM;
@@ -226,23 +235,30 @@ exit:
        kfree(buffer);
        return retval;
 }
-static DEVICE_ATTR(backlight, S_IWUGO, NULL, set_backlight);
+
+static struct device_attribute dev_lcd_line_attrs[] = {
+       lcd_line_attr(1),
+       lcd_line_attr(2),
+       __ATTR(backlight, S_IWUGO, NULL, set_backlight)
+};
 
 static void remove_lcd_files(struct interfacekit *kit)
 {
+       int i;
+
        if (kit->lcd_files_on) {
                dev_dbg(&kit->udev->dev, "Removing lcd files\n");
-               device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_1);
-               device_remove_file(&kit->intf->dev, &dev_attr_lcd_line_2);
-               device_remove_file(&kit->intf->dev, &dev_attr_backlight);
+
+               for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++)
+                       device_remove_file(kit->dev, &dev_lcd_line_attrs[i]);
        }
 }
 
 static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct usb_interface *intf = to_usb_interface(dev);
-       struct interfacekit *kit = usb_get_intfdata(intf);
+       struct interfacekit *kit = dev_get_drvdata(dev);
        int enable;
+       int i, rc;
        
        if (kit->ifkit->has_lcd == 0)
                return -ENODEV;
@@ -253,9 +269,12 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att
        if (enable) {
                if (!kit->lcd_files_on) {
                        dev_dbg(&kit->udev->dev, "Adding lcd files\n");
-                       device_create_file(&kit->intf->dev, &dev_attr_lcd_line_1);
-                       device_create_file(&kit->intf->dev, &dev_attr_lcd_line_2);
-                       device_create_file(&kit->intf->dev, &dev_attr_backlight);
+                       for (i=0; i<ARRAY_SIZE(dev_lcd_line_attrs); i++) {
+                               rc = device_create_file(kit->dev,
+                                       &dev_lcd_line_attrs[i]);
+                               if (rc)
+                                       goto out;
+                       }
                        kit->lcd_files_on = 1;
                }
        } else {
@@ -266,7 +285,13 @@ static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *att
        }
        
        return count;
+out:
+       while (i-- > 0)
+               device_remove_file(kit->dev, &dev_lcd_line_attrs[i]);
+
+       return rc;
 }
+
 static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files);
 
 static void interfacekit_irq(struct urb *urb, struct pt_regs *regs)
@@ -362,24 +387,24 @@ static void do_notify(void *data)
        for (i=0; i<kit->ifkit->inputs; i++) {
                if (test_and_clear_bit(i, &kit->input_events)) {
                        sprintf(sysfs_file, "input%d", i + 1);
-                       sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file);
+                       sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);
                }
        }
 
        for (i=0; i<kit->ifkit->sensors; i++) {
                if (test_and_clear_bit(i, &kit->sensor_events)) {
                        sprintf(sysfs_file, "sensor%d", i + 1);
-                       sysfs_notify(&kit->intf->dev.kobj, NULL, sysfs_file);
+                       sysfs_notify(&kit->dev->kobj, NULL, sysfs_file);
                }
        }
 }
 
 #define show_set_output(value)         \
-static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf,   \
-                                                       size_t count)   \
+static ssize_t set_output##value(struct device *dev,                   \
+                                       struct device_attribute *attr,  \
+                                       const char *buf, size_t count)  \
 {                                                                      \
-       struct usb_interface *intf = to_usb_interface(dev);             \
-       struct interfacekit *kit = usb_get_intfdata(intf);              \
+       struct interfacekit *kit = dev_get_drvdata(dev);                \
        int enabled;                                                    \
        int retval;                                                     \
                                                                        \
@@ -391,15 +416,19 @@ static ssize_t set_output##value(struct device *dev, struct device_attribute *at
        return retval ? retval : count;                                 \
 }                                                                      \
                                                                        \
-static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf)        \
+static ssize_t show_output##value(struct device *dev,                  \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
 {                                                                      \
-       struct usb_interface *intf = to_usb_interface(dev);             \
-       struct interfacekit *kit = usb_get_intfdata(intf);              \
+       struct interfacekit *kit = dev_get_drvdata(dev);                \
                                                                        \
        return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\
-}                                                                      \
-static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO,                   \
-               show_output##value, set_output##value);
+}
+
+#define output_attr(value)                                             \
+       __ATTR(output##value, S_IWUGO | S_IRUGO,                        \
+               show_output##value, set_output##value)
+
 show_set_output(1);
 show_set_output(2);
 show_set_output(3);
@@ -417,15 +446,24 @@ show_set_output(14);
 show_set_output(15);
 show_set_output(16);
 
+static struct device_attribute dev_output_attrs[] = {
+       output_attr(1), output_attr(2), output_attr(3), output_attr(4),
+       output_attr(5), output_attr(6), output_attr(7), output_attr(8),
+       output_attr(9), output_attr(10), output_attr(11), output_attr(12),
+       output_attr(13), output_attr(14), output_attr(15), output_attr(16)
+};
+
 #define show_input(value)      \
-static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \
+static ssize_t show_input##value(struct device *dev,                   \
+                       struct device_attribute *attr, char *buf)       \
 {                                                                      \
-       struct usb_interface *intf = to_usb_interface(dev);             \
-       struct interfacekit *kit = usb_get_intfdata(intf);              \
+       struct interfacekit *kit = dev_get_drvdata(dev);                \
                                                                        \
        return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]);       \
-}                                                                      \
-static DEVICE_ATTR(input##value, S_IRUGO, show_input##value, NULL);
+}
+
+#define input_attr(value)                                              \
+       __ATTR(input##value, S_IRUGO, show_input##value, NULL)
 
 show_input(1);
 show_input(2);
@@ -444,15 +482,25 @@ show_input(14);
 show_input(15);
 show_input(16);
 
+static struct device_attribute dev_input_attrs[] = {
+       input_attr(1), input_attr(2), input_attr(3), input_attr(4),
+       input_attr(5), input_attr(6), input_attr(7), input_attr(8),
+       input_attr(9), input_attr(10), input_attr(11), input_attr(12),
+       input_attr(13), input_attr(14), input_attr(15), input_attr(16)
+};
+
 #define show_sensor(value)     \
-static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf)        \
+static ssize_t show_sensor##value(struct device *dev,                  \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
 {                                                                      \
-       struct usb_interface *intf = to_usb_interface(dev);             \
-       struct interfacekit *kit = usb_get_intfdata(intf);              \
+       struct interfacekit *kit = dev_get_drvdata(dev);                \
                                                                        \
        return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]);      \
-}                                                                      \
-static DEVICE_ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL);
+}
+
+#define sensor_attr(value)                                             \
+       __ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL)
 
 show_sensor(1);
 show_sensor(2);
@@ -463,6 +511,11 @@ show_sensor(6);
 show_sensor(7);
 show_sensor(8);
 
+static struct device_attribute dev_sensor_attrs[] = {
+       sensor_attr(1), sensor_attr(2), sensor_attr(3), sensor_attr(4),
+       sensor_attr(5), sensor_attr(6), sensor_attr(7), sensor_attr(8)
+};
+
 static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
        struct usb_device *dev = interface_to_usbdev(intf);
@@ -471,6 +524,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
        struct interfacekit *kit;
        struct driver_interfacekit *ifkit;
        int pipe, maxp, rc = -ENOMEM;
+       int bit, value, i;
 
        ifkit = (struct driver_interfacekit *)id->driver_info;
        if (!ifkit)
@@ -493,6 +547,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
        if (!kit)
                goto out;
 
+       kit->dev_no = -1;
        kit->ifkit = ifkit;
        kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &kit->data_dma);
        if (!kit->data)
@@ -513,85 +568,80 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
 
        usb_set_intfdata(intf, kit);
 
+        do {
+                bit = find_first_zero_bit(&device_no, sizeof(device_no));
+                value = test_and_set_bit(bit, &device_no);
+        } while(value);
+        kit->dev_no = bit;
+
+        kit->dev = device_create(phidget_class, &kit->udev->dev, 0,
+                               "interfacekit%d", kit->dev_no);
+        if (IS_ERR(kit->dev)) {
+                rc = PTR_ERR(kit->dev);
+                kit->dev = NULL;
+                goto out;
+        }
+       dev_set_drvdata(kit->dev, kit);
+
        if (usb_submit_urb(kit->irq, GFP_KERNEL)) {
                rc = -EIO;
                goto out;
        }
 
-       if (ifkit->outputs >= 4) {
-               device_create_file(&intf->dev, &dev_attr_output1);
-               device_create_file(&intf->dev, &dev_attr_output2);
-               device_create_file(&intf->dev, &dev_attr_output3);
-               device_create_file(&intf->dev, &dev_attr_output4);
-       }
-       if (ifkit->outputs >= 8) {
-               device_create_file(&intf->dev, &dev_attr_output5);
-               device_create_file(&intf->dev, &dev_attr_output6);
-               device_create_file(&intf->dev, &dev_attr_output7);
-               device_create_file(&intf->dev, &dev_attr_output8);
-       } 
-       if (ifkit->outputs == 16) {
-               device_create_file(&intf->dev, &dev_attr_output9);
-               device_create_file(&intf->dev, &dev_attr_output10);
-               device_create_file(&intf->dev, &dev_attr_output11);
-               device_create_file(&intf->dev, &dev_attr_output12);
-               device_create_file(&intf->dev, &dev_attr_output13);
-               device_create_file(&intf->dev, &dev_attr_output14);
-               device_create_file(&intf->dev, &dev_attr_output15);
-               device_create_file(&intf->dev, &dev_attr_output16);
+       for (i=0; i<ifkit->outputs; i++ ) {
+               rc = device_create_file(kit->dev, &dev_output_attrs[i]);
+               if (rc)
+                       goto out2;
        }
 
-       if (ifkit->inputs >= 4) {
-               device_create_file(&intf->dev, &dev_attr_input1);
-               device_create_file(&intf->dev, &dev_attr_input2);
-               device_create_file(&intf->dev, &dev_attr_input3);
-               device_create_file(&intf->dev, &dev_attr_input4);
-       }
-       if (ifkit->inputs >= 8) {
-               device_create_file(&intf->dev, &dev_attr_input5);
-               device_create_file(&intf->dev, &dev_attr_input6);
-               device_create_file(&intf->dev, &dev_attr_input7);
-               device_create_file(&intf->dev, &dev_attr_input8);
-       }
-       if (ifkit->inputs == 16) {
-               device_create_file(&intf->dev, &dev_attr_input9);
-               device_create_file(&intf->dev, &dev_attr_input10);
-               device_create_file(&intf->dev, &dev_attr_input11);
-               device_create_file(&intf->dev, &dev_attr_input12);
-               device_create_file(&intf->dev, &dev_attr_input13);
-               device_create_file(&intf->dev, &dev_attr_input14);
-               device_create_file(&intf->dev, &dev_attr_input15);
-               device_create_file(&intf->dev, &dev_attr_input16);
+       for (i=0; i<ifkit->inputs; i++ ) {
+               rc = device_create_file(kit->dev, &dev_input_attrs[i]);
+               if (rc)
+                       goto out3;
        }
 
-       if (ifkit->sensors >= 4) {
-               device_create_file(&intf->dev, &dev_attr_sensor1);
-               device_create_file(&intf->dev, &dev_attr_sensor2);
-               device_create_file(&intf->dev, &dev_attr_sensor3);
-               device_create_file(&intf->dev, &dev_attr_sensor4);
-       }
-       if (ifkit->sensors >= 7) {
-               device_create_file(&intf->dev, &dev_attr_sensor5);
-               device_create_file(&intf->dev, &dev_attr_sensor6);
-               device_create_file(&intf->dev, &dev_attr_sensor7);
+       for (i=0; i<ifkit->sensors; i++ ) {
+               rc = device_create_file(kit->dev, &dev_sensor_attrs[i]);
+               if (rc)
+                       goto out4;
        }
-       if (ifkit->sensors == 8)
-               device_create_file(&intf->dev, &dev_attr_sensor8);
 
-       if (ifkit->has_lcd)
-               device_create_file(&intf->dev, &dev_attr_lcd);
+       if (ifkit->has_lcd) {
+               rc = device_create_file(kit->dev, &dev_attr_lcd);
+               if (rc)
+                       goto out4;
+
+       }
 
        dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n",
                        ifkit->sensors, ifkit->inputs, ifkit->outputs);
 
        return 0;
 
+out4:
+       while (i-- > 0)
+               device_remove_file(kit->dev, &dev_sensor_attrs[i]);
+
+       i = ifkit->inputs;
+out3:
+       while (i-- > 0)
+               device_remove_file(kit->dev, &dev_input_attrs[i]);
+
+       i = ifkit->outputs;
+out2:
+       while (i-- > 0)
+               device_remove_file(kit->dev, &dev_output_attrs[i]);
 out:
        if (kit) {
                if (kit->irq)
                        usb_free_urb(kit->irq);
                if (kit->data)
                        usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
+               if (kit->dev)
+                       device_unregister(kit->dev);
+               if (kit->dev_no >= 0)
+                       clear_bit(kit->dev_no, &device_no);
+
                kfree(kit);
        }
 
@@ -601,6 +651,7 @@ out:
 static void interfacekit_disconnect(struct usb_interface *interface)
 {
        struct interfacekit *kit;
+       int i;
 
        kit = usb_get_intfdata(interface);
        usb_set_intfdata(interface, NULL);
@@ -613,73 +664,28 @@ static void interfacekit_disconnect(struct usb_interface *interface)
 
        cancel_delayed_work(&kit->do_notify);
 
-       if (kit->ifkit->outputs >= 4) {
-               device_remove_file(&interface->dev, &dev_attr_output1);
-               device_remove_file(&interface->dev, &dev_attr_output2);
-               device_remove_file(&interface->dev, &dev_attr_output3);
-               device_remove_file(&interface->dev, &dev_attr_output4);
-       }
-       if (kit->ifkit->outputs >= 8) {
-               device_remove_file(&interface->dev, &dev_attr_output5);
-               device_remove_file(&interface->dev, &dev_attr_output6);
-               device_remove_file(&interface->dev, &dev_attr_output7);
-               device_remove_file(&interface->dev, &dev_attr_output8);
-       }
-       if (kit->ifkit->outputs == 16) {
-               device_remove_file(&interface->dev, &dev_attr_output9);
-               device_remove_file(&interface->dev, &dev_attr_output10);
-               device_remove_file(&interface->dev, &dev_attr_output11);
-               device_remove_file(&interface->dev, &dev_attr_output12);
-               device_remove_file(&interface->dev, &dev_attr_output13);
-               device_remove_file(&interface->dev, &dev_attr_output14);
-               device_remove_file(&interface->dev, &dev_attr_output15);
-               device_remove_file(&interface->dev, &dev_attr_output16);
-       }
+       for (i=0; i<kit->ifkit->outputs; i++)
+               device_remove_file(kit->dev, &dev_output_attrs[i]);
 
-       if (kit->ifkit->inputs >= 4) {
-               device_remove_file(&interface->dev, &dev_attr_input1);
-               device_remove_file(&interface->dev, &dev_attr_input2);
-               device_remove_file(&interface->dev, &dev_attr_input3);
-               device_remove_file(&interface->dev, &dev_attr_input4);
-       }
-       if (kit->ifkit->inputs >= 8) {
-               device_remove_file(&interface->dev, &dev_attr_input5);
-               device_remove_file(&interface->dev, &dev_attr_input6);
-               device_remove_file(&interface->dev, &dev_attr_input7);
-               device_remove_file(&interface->dev, &dev_attr_input8);
-       }
-       if (kit->ifkit->inputs == 16) {
-               device_remove_file(&interface->dev, &dev_attr_input9);
-               device_remove_file(&interface->dev, &dev_attr_input10);
-               device_remove_file(&interface->dev, &dev_attr_input11);
-               device_remove_file(&interface->dev, &dev_attr_input12);
-               device_remove_file(&interface->dev, &dev_attr_input13);
-               device_remove_file(&interface->dev, &dev_attr_input14);
-               device_remove_file(&interface->dev, &dev_attr_input15);
-               device_remove_file(&interface->dev, &dev_attr_input16);
-       }
+       for (i=0; i<kit->ifkit->inputs; i++)
+               device_remove_file(kit->dev, &dev_input_attrs[i]);
 
-       if (kit->ifkit->sensors >= 4) {
-               device_remove_file(&interface->dev, &dev_attr_sensor1);
-               device_remove_file(&interface->dev, &dev_attr_sensor2);
-               device_remove_file(&interface->dev, &dev_attr_sensor3);
-               device_remove_file(&interface->dev, &dev_attr_sensor4);
-       }
-       if (kit->ifkit->sensors >= 7) {
-               device_remove_file(&interface->dev, &dev_attr_sensor5);
-               device_remove_file(&interface->dev, &dev_attr_sensor6);
-               device_remove_file(&interface->dev, &dev_attr_sensor7);
+       for (i=0; i<kit->ifkit->sensors; i++)
+               device_remove_file(kit->dev, &dev_sensor_attrs[i]);
+
+       if (kit->ifkit->has_lcd) {
+               device_remove_file(kit->dev, &dev_attr_lcd);
+               remove_lcd_files(kit);
        }
-       if (kit->ifkit->sensors == 8)
-               device_remove_file(&interface->dev, &dev_attr_sensor8);
 
-       if (kit->ifkit->has_lcd)
-               device_remove_file(&interface->dev, &dev_attr_lcd);
+       device_unregister(kit->dev);
 
        dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
                kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs);
 
        usb_put_dev(kit->udev);
+       clear_bit(kit->dev_no, &device_no);
+
        kfree(kit);
 }
 
diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c
new file mode 100644 (file)
index 0000000..6b59b62
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * USB Phidget MotorControl driver
+ *
+ * Copyright (C) 2006  Sean Young <sean@mess.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "phidget.h"
+
+#define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
+#define DRIVER_DESC "USB PhidgetMotorControl Driver"
+
+#define USB_VENDOR_ID_GLAB             0x06c2
+#define USB_DEVICE_ID_MOTORCONTROL     0x0058
+
+#define URB_INT_SIZE                   8
+
+static unsigned long device_no;
+
+struct motorcontrol {
+       struct usb_device *udev;
+       struct usb_interface *intf;
+       struct device *dev;
+       int dev_no;
+       u8 inputs[4];
+       s8 desired_speed[2];
+       s8 speed[2];
+       s16 _current[2];
+       s8 acceleration[2];
+       struct urb *irq;
+       unsigned char *data;
+       dma_addr_t data_dma;
+
+       struct work_struct do_notify;
+       unsigned long input_events;
+       unsigned long speed_events;
+       unsigned long exceed_events;
+};
+
+static struct usb_device_id id_table[] = {
+       { USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_MOTORCONTROL) },
+       {}
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+static int set_motor(struct motorcontrol *mc, int motor)
+{
+       u8 *buffer;
+       int speed, speed2, acceleration;
+       int retval;
+
+       buffer = kzalloc(8, GFP_KERNEL);
+       if (!buffer) {
+               dev_err(&mc->intf->dev, "%s - out of memory\n", __FUNCTION__);
+               return -ENOMEM;
+       }
+
+       acceleration = mc->acceleration[motor] * 10;
+       /* -127 <= speed <= 127 */
+       speed = (mc->desired_speed[motor] * 127) / 100;
+       /* -0x7300 <= speed2 <= 0x7300 */
+       speed2 = (mc->desired_speed[motor] * 230 * 128) / 100;
+
+       buffer[0] = motor;
+       buffer[1] = speed;
+       buffer[2] = acceleration >> 8;
+       buffer[3] = acceleration;
+       buffer[4] = speed2 >> 8;
+       buffer[5] = speed2;
+
+       retval = usb_control_msg(mc->udev,
+                        usb_sndctrlpipe(mc->udev, 0),
+                        0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
+
+       if (retval != 8)
+               dev_err(&mc->intf->dev, "usb_control_msg returned %d\n",
+                               retval);
+       kfree(buffer);
+
+       return retval < 0 ? retval : 0;
+}
+
+static void motorcontrol_irq(struct urb *urb, struct pt_regs *regs)
+{
+       struct motorcontrol *mc = urb->context;
+       unsigned char *buffer = mc->data;
+       int i, level;
+       int status;
+
+       switch (urb->status) {
+       case 0:                 /* success */
+               break;
+       case -ECONNRESET:       /* unlink */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       /* -EPIPE:  should clear the halt */
+       default:                /* error */
+               goto resubmit;
+       }
+
+       /* digital inputs */
+       for (i=0; i<4; i++) {
+               level = (buffer[0] >> i) & 1;
+               if (mc->inputs[i] != level) {
+                       mc->inputs[i] = level;
+                       set_bit(i, &mc->input_events);
+               }
+       }
+
+       /* motor speed */
+       if (buffer[2] == 0) {
+               for (i=0; i<2; i++) {
+               level = ((s8)buffer[4+i]) * 100 / 127;
+                       if (mc->speed[i] != level) {
+                               mc->speed[i] = level;
+                               set_bit(i, &mc->speed_events);
+                       }
+               }
+       } else {
+               int index = buffer[3] & 1;
+
+               level = ((s8)buffer[4] << 8) | buffer[5];
+               level = level * 100 / 29440;
+               if (mc->speed[index] != level) {
+                       mc->speed[index] = level;
+                       set_bit(index, &mc->speed_events);
+               }
+
+               level = ((s8)buffer[6] << 8) | buffer[7];
+               mc->_current[index] = level * 100 / 1572;
+       }
+
+       if (buffer[1] & 1)
+               set_bit(0, &mc->exceed_events);
+
+       if (buffer[1] & 2)
+               set_bit(1, &mc->exceed_events);
+
+       if (mc->input_events || mc->exceed_events || mc->speed_events)
+               schedule_work(&mc->do_notify);
+
+resubmit:
+       status = usb_submit_urb(urb, SLAB_ATOMIC);
+       if (status)
+               dev_err(&mc->intf->dev,
+                       "can't resubmit intr, %s-%s/motorcontrol0, status %d",
+                       mc->udev->bus->bus_name,
+                       mc->udev->devpath, status);
+}
+
+static void do_notify(void *data)
+{
+       struct motorcontrol *mc = data;
+       int i;
+       char sysfs_file[8];
+
+       for (i=0; i<4; i++) {
+               if (test_and_clear_bit(i, &mc->input_events)) {
+                       sprintf(sysfs_file, "input%d", i);
+                       sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
+               }
+       }
+
+       for (i=0; i<2; i++) {
+               if (test_and_clear_bit(i, &mc->speed_events)) {
+                       sprintf(sysfs_file, "speed%d", i);
+                       sysfs_notify(&mc->dev->kobj, NULL, sysfs_file);
+               }
+       }
+
+       for (i=0; i<2; i++) {
+               if (test_and_clear_bit(i, &mc->exceed_events))
+                       dev_warn(&mc->intf->dev,
+                               "motor #%d exceeds 1.5 Amp current limit\n", i);
+       }
+}
+
+#define show_set_speed(value)          \
+static ssize_t set_speed##value(struct device *dev,                    \
+                                       struct device_attribute *attr,  \
+                                       const char *buf, size_t count)  \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+       int speed;                                                      \
+       int retval;                                                     \
+                                                                       \
+       if (sscanf(buf, "%d", &speed) < 1)                              \
+               return -EINVAL;                                         \
+                                                                       \
+       if (speed < -100 || speed > 100)                                \
+               return -EINVAL;                                         \
+                                                                       \
+       mc->desired_speed[value] = speed;                               \
+                                                                       \
+       retval = set_motor(mc, value);                                  \
+                                                                       \
+       return retval ? retval : count;                                 \
+}                                                                      \
+                                                                       \
+static ssize_t show_speed##value(struct device *dev,                   \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+                                                                       \
+       return sprintf(buf, "%d\n", mc->speed[value]);                  \
+}
+
+#define speed_attr(value)                                              \
+       __ATTR(speed##value, S_IWUGO | S_IRUGO,                         \
+               show_speed##value, set_speed##value)
+
+show_set_speed(0);
+show_set_speed(1);
+
+#define show_set_acceleration(value)           \
+static ssize_t set_acceleration##value(struct device *dev,             \
+                                       struct device_attribute *attr,  \
+                                       const char *buf, size_t count)  \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+       int acceleration;                                               \
+       int retval;                                                     \
+                                                                       \
+       if (sscanf(buf, "%d", &acceleration) < 1)                       \
+               return -EINVAL;                                         \
+                                                                       \
+       if (acceleration < 0 || acceleration > 100)                     \
+               return -EINVAL;                                         \
+                                                                       \
+       mc->acceleration[value] = acceleration;                         \
+                                                                       \
+       retval = set_motor(mc, value);                                  \
+                                                                       \
+       return retval ? retval : count;                                 \
+}                                                                      \
+                                                                       \
+static ssize_t show_acceleration##value(struct device *dev,            \
+                                       struct device_attribute *attr,  \
+                                                       char *buf)      \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+                                                                       \
+       return sprintf(buf, "%d\n", mc->acceleration[value]);           \
+}
+
+#define acceleration_attr(value)       \
+       __ATTR(acceleration##value, S_IWUGO | S_IRUGO,                  \
+               show_acceleration##value, set_acceleration##value)
+
+show_set_acceleration(0);
+show_set_acceleration(1);
+
+#define show_current(value)    \
+static ssize_t show_current##value(struct device *dev,                 \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+                                                                       \
+       return sprintf(buf, "%dmA\n", (int)mc->_current[value]);        \
+}
+
+#define current_attr(value)    \
+       __ATTR(current##value, S_IRUGO, show_current##value, NULL)
+
+show_current(0);
+show_current(1);
+
+#define show_input(value)      \
+static ssize_t show_input##value(struct device *dev,                   \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
+{                                                                      \
+       struct motorcontrol *mc = dev_get_drvdata(dev);                 \
+                                                                       \
+       return sprintf(buf, "%d\n", (int)mc->inputs[value]);            \
+}
+
+#define input_attr(value)      \
+       __ATTR(input##value, S_IRUGO, show_input##value, NULL)
+
+show_input(0);
+show_input(1);
+show_input(2);
+show_input(3);
+
+static struct device_attribute dev_attrs[] = {
+       input_attr(0),
+       input_attr(1),
+       input_attr(2),
+       input_attr(3),
+       speed_attr(0),
+       speed_attr(1),
+       acceleration_attr(0),
+       acceleration_attr(1),
+       current_attr(0),
+       current_attr(1)
+};
+
+static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       struct usb_device *dev = interface_to_usbdev(intf);
+       struct usb_host_interface *interface;
+       struct usb_endpoint_descriptor *endpoint;
+       struct motorcontrol *mc;
+       int pipe, maxp, rc = -ENOMEM;
+       int bit, value, i;
+
+       interface = intf->cur_altsetting;
+       if (interface->desc.bNumEndpoints != 1)
+               return -ENODEV;
+
+       endpoint = &interface->endpoint[0].desc;
+       if (!(endpoint->bEndpointAddress & 0x80))
+               return -ENODEV;
+
+       /*
+        * bmAttributes
+        */
+       pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+       maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+       mc = kzalloc(sizeof(*mc), GFP_KERNEL);
+       if (!mc)
+               goto out;
+
+       mc->dev_no = -1;
+       mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, SLAB_ATOMIC, &mc->data_dma);
+       if (!mc->data)
+               goto out;
+
+       mc->irq = usb_alloc_urb(0, GFP_KERNEL);
+       if (!mc->irq)
+               goto out;
+
+       mc->udev = usb_get_dev(dev);
+       mc->intf = intf;
+       mc->acceleration[0] = mc->acceleration[1] = 10;
+       INIT_WORK(&mc->do_notify, do_notify, mc);
+       usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data,
+                       maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp,
+                       motorcontrol_irq, mc, endpoint->bInterval);
+       mc->irq->transfer_dma = mc->data_dma;
+       mc->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       usb_set_intfdata(intf, mc);
+
+       do {
+               bit = find_first_zero_bit(&device_no, sizeof(device_no));
+               value = test_and_set_bit(bit, &device_no);
+       } while(value);
+       mc->dev_no = bit;
+
+       mc->dev = device_create(phidget_class, &mc->udev->dev, 0,
+                               "motorcontrol%d", mc->dev_no);
+       if (IS_ERR(mc->dev)) {
+               rc = PTR_ERR(mc->dev);
+               mc->dev = NULL;
+               goto out;
+       }
+
+       dev_set_drvdata(mc->dev, mc);
+
+       if (usb_submit_urb(mc->irq, GFP_KERNEL)) {
+               rc = -EIO;
+               goto out;
+       }
+
+       for (i=0; i<ARRAY_SIZE(dev_attrs); i++) {
+               rc = device_create_file(mc->dev, &dev_attrs[i]);
+               if (rc)
+                       goto out2;
+       }
+
+       dev_info(&intf->dev, "USB PhidgetMotorControl attached\n");
+
+       return 0;
+out2:
+       while (i-- > 0)
+               device_remove_file(mc->dev, &dev_attrs[i]);
+out:
+       if (mc) {
+               if (mc->irq)
+                       usb_free_urb(mc->irq);
+               if (mc->data)
+                       usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
+               if (mc->dev)
+                       device_unregister(mc->dev);
+               if (mc->dev_no >= 0)
+                       clear_bit(mc->dev_no, &device_no);
+
+               kfree(mc);
+       }
+
+       return rc;
+}
+
+static void motorcontrol_disconnect(struct usb_interface *interface)
+{
+       struct motorcontrol *mc;
+       int i;
+
+       mc = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+       if (!mc)
+               return;
+
+       usb_kill_urb(mc->irq);
+       usb_free_urb(mc->irq);
+       usb_buffer_free(mc->udev, URB_INT_SIZE, mc->data, mc->data_dma);
+
+       cancel_delayed_work(&mc->do_notify);
+
+       for (i=0; i<ARRAY_SIZE(dev_attrs); i++)
+               device_remove_file(mc->dev, &dev_attrs[i]);
+
+       device_unregister(mc->dev);
+
+       usb_put_dev(mc->udev);
+       clear_bit(mc->dev_no, &device_no);
+       kfree(mc);
+
+       dev_info(&interface->dev, "USB PhidgetMotorControl detached\n");
+}
+
+static struct usb_driver motorcontrol_driver = {
+       .name = "phidgetmotorcontrol",
+       .probe = motorcontrol_probe,
+       .disconnect = motorcontrol_disconnect,
+       .id_table = id_table
+};
+
+static int __init motorcontrol_init(void)
+{
+       int retval = 0;
+
+       retval = usb_register(&motorcontrol_driver);
+       if (retval)
+               err("usb_register failed. Error number %d", retval);
+
+       return retval;
+}
+
+static void __exit motorcontrol_exit(void)
+{
+       usb_deregister(&motorcontrol_driver);
+}
+
+module_init(motorcontrol_init);
+module_exit(motorcontrol_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
index c0df79c9653810b17e0e87737eb9e1ab37b1dad0..7163f05c5b27063eb18b7554372fe99280205c8b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * USB PhidgetServo driver 1.0
  *
- * Copyright (C) 2004 Sean Young <sean@mess.org>
+ * Copyright (C) 2004, 2006 Sean Young <sean@mess.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  *
  * CAUTION: Generally you should use 0 < degrees < 180 as anything else
  * is probably beyond the range of your servo and may damage it.
- *
- * Jun 16, 2004: Sean Young <sean@mess.org>
- *  - cleanups
- *  - was using memory after kfree()
- * Aug 8, 2004: Sean Young <sean@mess.org>
- *  - set the highest angle as high as the hardware allows, there are 
- *    some odd servos out there
- *
  */
 
 #include <linux/kernel.h>
@@ -32,6 +24,8 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 
+#include "phidget.h"
+
 #define DRIVER_AUTHOR "Sean Young <sean@mess.org>"
 #define DRIVER_DESC "USB PhidgetServo Driver"
 
@@ -70,8 +64,12 @@ static struct usb_device_id id_table[] = {
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
+static int unsigned long device_no;
+
 struct phidget_servo {
        struct usb_device *udev;
+       struct device *dev;
+       int dev_no;
        ulong type;
        int pulse[4];
        int degrees[4];
@@ -203,16 +201,16 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
 }
 
 #define show_set(value)        \
-static ssize_t set_servo##value (struct device *dev, struct device_attribute *attr,                    \
+static ssize_t set_servo##value (struct device *dev,                   \
+                                       struct device_attribute *attr,  \
                                        const char *buf, size_t count)  \
 {                                                                      \
        int degrees, minutes, retval;                                   \
-       struct usb_interface *intf = to_usb_interface (dev);            \
-       struct phidget_servo *servo = usb_get_intfdata (intf);          \
+       struct phidget_servo *servo = dev_get_drvdata(dev);             \
                                                                        \
        minutes = 0;                                                    \
        /* must at least convert degrees */                             \
-       if (sscanf (buf, "%d.%d", &degrees, &minutes) < 1) {            \
+       if (sscanf(buf, "%d.%d", &degrees, &minutes) < 1) {             \
                return -EINVAL;                                         \
        }                                                               \
                                                                        \
@@ -220,86 +218,127 @@ static ssize_t set_servo##value (struct device *dev, struct device_attribute *at
                return -EINVAL;                                         \
                                                                        \
        if (servo->type & SERVO_VERSION_30)                             \
-               retval = change_position_v30 (servo, value, degrees,    \
+               retval = change_position_v30(servo, value, degrees,     \
                                                        minutes);       \
        else                                                            \
-               retval = change_position_v20 (servo, value, degrees,    \
+               retval = change_position_v20(servo, value, degrees,     \
                                                        minutes);       \
                                                                        \
        return retval < 0 ? retval : count;                             \
 }                                                                      \
                                                                        \
-static ssize_t show_servo##value (struct device *dev, struct device_attribute *attr, char *buf)        \
+static ssize_t show_servo##value (struct device *dev,                  \
+                                       struct device_attribute *attr,  \
+                                       char *buf)                      \
 {                                                                      \
-       struct usb_interface *intf = to_usb_interface (dev);            \
-       struct phidget_servo *servo = usb_get_intfdata (intf);          \
+       struct phidget_servo *servo = dev_get_drvdata(dev);             \
                                                                        \
-       return sprintf (buf, "%d.%02d\n", servo->degrees[value],        \
+       return sprintf(buf, "%d.%02d\n", servo->degrees[value],         \
                                servo->minutes[value]);                 \
-}                                                                      \
-static DEVICE_ATTR(servo##value, S_IWUGO | S_IRUGO,                    \
-         show_servo##value, set_servo##value);
+}
 
+#define servo_attr(value)                                              \
+       __ATTR(servo##value, S_IWUGO | S_IRUGO,                         \
+               show_servo##value, set_servo##value)
 show_set(0);
 show_set(1);
 show_set(2);
 show_set(3);
 
+static struct device_attribute dev_attrs[] = {
+       servo_attr(0), servo_attr(1), servo_attr(2), servo_attr(3)
+};
+
 static int
 servo_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
        struct usb_device *udev = interface_to_usbdev(interface);
        struct phidget_servo *dev;
+       int bit, value, rc;
+       int servo_count, i;
 
        dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL);
        if (dev == NULL) {
                dev_err(&interface->dev, "%s - out of memory\n", __FUNCTION__);
-               return -ENOMEM;
+               rc = -ENOMEM;
+               goto out;
        }
 
        dev->udev = usb_get_dev(udev);
        dev->type = id->driver_info;
+       dev->dev_no = -1;
        usb_set_intfdata(interface, dev);
 
-       device_create_file(&interface->dev, &dev_attr_servo0);
-       if (dev->type & SERVO_COUNT_QUAD) {
-               device_create_file(&interface->dev, &dev_attr_servo1);
-               device_create_file(&interface->dev, &dev_attr_servo2);
-               device_create_file(&interface->dev, &dev_attr_servo3);
+        do {
+                bit = find_first_zero_bit(&device_no, sizeof(device_no));
+                value = test_and_set_bit(bit, &device_no);
+        } while (value);
+       dev->dev_no = bit;
+
+       dev->dev = device_create(phidget_class, &dev->udev->dev, 0,
+                                "servo%d", dev->dev_no);
+       if (IS_ERR(dev->dev)) {
+               rc = PTR_ERR(dev->dev);
+               dev->dev = NULL;
+               goto out;
+       }
+
+       servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
+
+       for (i=0; i<servo_count; i++) {
+               rc = device_create_file(dev->dev, &dev_attrs[i]);
+               if (rc)
+                       goto out2;
        }
 
        dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n",
-               dev->type & SERVO_COUNT_QUAD ? 4 : 1,
-               dev->type & SERVO_VERSION_30 ? 3 : 2);
+               servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2);
 
-       if(!(dev->type & SERVO_VERSION_30))
+       if (!(dev->type & SERVO_VERSION_30))
                dev_info(&interface->dev,
                         "WARNING: v2.0 not tested! Please report if it works.\n");
 
        return 0;
+out2:
+       while (i-- > 0)
+               device_remove_file(dev->dev, &dev_attrs[i]);
+out:
+       if (dev) {
+               if (dev->dev)
+                       device_unregister(dev->dev);
+               if (dev->dev_no >= 0)
+                       clear_bit(dev->dev_no, &device_no);
+
+               kfree(dev);
+       }
+
+       return rc;
 }
 
 static void
 servo_disconnect(struct usb_interface *interface)
 {
        struct phidget_servo *dev;
+       int servo_count, i;
 
        dev = usb_get_intfdata(interface);
        usb_set_intfdata(interface, NULL);
 
-       device_remove_file(&interface->dev, &dev_attr_servo0);
-       if (dev->type & SERVO_COUNT_QUAD) {
-               device_remove_file(&interface->dev, &dev_attr_servo1);
-               device_remove_file(&interface->dev, &dev_attr_servo2);
-               device_remove_file(&interface->dev, &dev_attr_servo3);
-       }
+       if (!dev)
+               return;
+
+       servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1;
+
+       for (i=0; i<servo_count; i++)
+               device_remove_file(dev->dev, &dev_attrs[i]);
 
+       device_unregister(dev->dev);
        usb_put_dev(dev->udev);
 
        dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n",
-               dev->type & SERVO_COUNT_QUAD ? 4 : 1,
-               dev->type & SERVO_VERSION_30 ? 3 : 2);
+               servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2);
 
+       clear_bit(dev->dev_no, &device_no);
        kfree(dev);
 }
 
index e16582f3733c16a093ad30b4dbcf417093098f4a..a44124c7e8514860861aa291ee4ded07afe53145 100644 (file)
@@ -3179,7 +3179,7 @@ sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 }
 #endif
 
-static struct file_operations usb_sisusb_fops = {
+static const struct file_operations usb_sisusb_fops = {
        .owner =        THIS_MODULE,
        .open =         sisusb_open,
        .release =      sisusb_release,
diff --git a/drivers/usb/misc/usb_u132.h b/drivers/usb/misc/usb_u132.h
new file mode 100644 (file)
index 0000000..551ba89
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+* Common Header File for the Elan Digital Systems U132 adapter
+* this file should be included by both the "ftdi-u132" and
+* the "u132-hcd" modules.
+*
+* Copyright(C) 2006 Elan Digital Systems Limited
+*(http://www.elandigitalsystems.com)
+*
+* Author and Maintainer - Tony Olech - Elan Digital Systems
+*(tony.olech@elandigitalsystems.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.
+*
+*
+* The driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
+* based on various USB client drivers in the 2.6.15 linux kernel
+* with constant reference to the 3rd Edition of Linux Device Drivers
+* published by O'Reilly
+*
+* The U132 adapter is a USB to CardBus adapter specifically designed
+* for PC cards that contain an OHCI host controller. Typical PC cards
+* are the Orange Mobile 3G Option GlobeTrotter Fusion card.
+*
+* The U132 adapter will *NOT *work with PC cards that do not contain
+* an OHCI controller. A simple way to test whether a PC card has an
+* OHCI controller as an interface is to insert the PC card directly
+* into a laptop(or desktop) with a CardBus slot and if "lspci" shows
+* a new USB controller and "lsusb -v" shows a new OHCI Host Controller
+* then there is a good chance that the U132 adapter will support the
+* PC card.(you also need the specific client driver for the PC card)
+*
+* Please inform the Author and Maintainer about any PC cards that
+* contain OHCI Host Controller and work when directly connected to
+* an embedded CardBus slot but do not work when they are connected
+* via an ELAN U132 adapter.
+*
+* The driver consists of two modules, the "ftdi-u132" module is
+* a USB client driver that interfaces to the FTDI chip within
+* the U132 adapter manufactured by Elan Digital Systems, and the
+* "u132-hcd" module is a USB host controller driver that talks
+* to the OHCI controller within CardBus card that are inserted
+* in the U132 adapter.
+*
+* The "ftdi-u132" module should be loaded automatically by the
+* hot plug system when the U132 adapter is plugged in. The module
+* initialises the adapter which mostly consists of synchronising
+* the FTDI chip, before continuously polling the adapter to detect
+* PC card insertions. As soon as a PC card containing a recognised
+* OHCI controller is seen the "ftdi-u132" module explicitly requests
+* the kernel to load the "u132-hcd" module.
+*
+* The "ftdi-u132" module provides the interface to the inserted
+* PC card and the "u132-hcd" module uses the API to send and recieve
+* data. The API features call-backs, so that part of the "u132-hcd"
+* module code will run in the context of one of the kernel threads
+* of the "ftdi-u132" module.
+*
+*/
+int ftdi_elan_switch_on_diagnostics(int number);
+void ftdi_elan_gone_away(struct platform_device *pdev);
+void start_usb_lock_device_tracing(void);
+struct u132_platform_data {
+        u16 vendor;
+        u16 device;
+        u8 potpg;
+        void (*port_power) (struct device *dev, int is_on);
+        void (*reset) (struct device *dev);
+};
+int usb_ftdi_elan_edset_single(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_output(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_empty(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_input(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
+        void *endp, struct urb *urb, u8 address, u8 ep_number, u8 toggle_bits,
+        void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
+        int toggle_bits, int error_count, int condition_code, int repeat_number,
+         int halted, int skipped, int actual, int non_null));
+int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
+        void *endp);
index e095772dd8e9eebc2887afc835b105d72af09d03..dbaca9f1efadc02de7d6544523e75a039f26a104 100644 (file)
@@ -239,7 +239,7 @@ error:
        return retval;
 }
 
-static struct file_operations lcd_fops = {
+static const struct file_operations lcd_fops = {
         .owner =        THIS_MODULE,
         .read =         lcd_read,
         .write =        lcd_write,
@@ -290,9 +290,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
                endpoint = &iface_desc->endpoint[i].desc;
 
                if (!dev->bulk_in_endpointAddr &&
-                   (endpoint->bEndpointAddress & USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                                       == USB_ENDPOINT_XFER_BULK)) {
+                   usb_endpoint_is_bulk_in(endpoint)) {
                        /* we found a bulk in endpoint */
                        buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
                        dev->bulk_in_size = buffer_size;
@@ -305,9 +303,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id
                }
 
                if (!dev->bulk_out_endpointAddr &&
-                   !(endpoint->bEndpointAddress & USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                                       == USB_ENDPOINT_XFER_BULK)) {
+                   usb_endpoint_is_bulk_out(endpoint)) {
                        /* we found a bulk out endpoint */
                        dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
                }
index 0c5ee0ad6bb952fecc1eda6708cbab753ebc4120..49c5c5c4c431ee2aabd7ce0b081e913d2634b6f6 100644 (file)
@@ -108,22 +108,34 @@ static int led_probe(struct usb_interface *interface, const struct usb_device_id
        dev = kzalloc(sizeof(struct usb_led), GFP_KERNEL);
        if (dev == NULL) {
                dev_err(&interface->dev, "Out of memory\n");
-               goto error;
+               goto error_mem;
        }
 
        dev->udev = usb_get_dev(udev);
 
        usb_set_intfdata (interface, dev);
 
-       device_create_file(&interface->dev, &dev_attr_blue);
-       device_create_file(&interface->dev, &dev_attr_red);
-       device_create_file(&interface->dev, &dev_attr_green);
+       retval = device_create_file(&interface->dev, &dev_attr_blue);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_red);
+       if (retval)
+               goto error;
+       retval = device_create_file(&interface->dev, &dev_attr_green);
+       if (retval)
+               goto error;
 
        dev_info(&interface->dev, "USB LED device now attached\n");
        return 0;
 
 error:
+       device_remove_file(&interface->dev, &dev_attr_blue);
+       device_remove_file(&interface->dev, &dev_attr_red);
+       device_remove_file(&interface->dev, &dev_attr_green);
+       usb_set_intfdata (interface, NULL);
+       usb_put_dev(dev->udev);
        kfree(dev);
+error_mem:
        return retval;
 }
 
index 275a66f8305878b2f435506e675a851454b586af..394bbf2f68d44f0b81807773be8a12e992fb690c 100644 (file)
@@ -265,7 +265,6 @@ static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus)
        ubus->mon_bus = NULL;
        mbus->u_bus = NULL;
        mb();
-       // usb_bus_put(ubus);
 }
 
 /*
@@ -297,12 +296,12 @@ static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus)
        INIT_LIST_HEAD(&mbus->r_list);
 
        /*
-        * This usb_bus_get here is superfluous, because we receive
-        * a notification if usb_bus is about to be removed.
+        * We don't need to take a reference to ubus, because we receive
+        * a notification if the bus is about to be removed.
         */
-       // usb_bus_get(ubus);
        mbus->u_bus = ubus;
        ubus->mon_bus = mbus;
+       mbus->uses_dma = ubus->uses_dma;
 
        rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
        if (rc <= 0 || rc >= NAMESZ)
index 1fe01d994a793f79ec801a663a8ddb1eec54a345..f6d1491256c4453ebfb1b06f2a908b4c29d364fd 100644 (file)
@@ -28,7 +28,7 @@ static int mon_stat_open(struct inode *inode, struct file *file)
        if ((sp = kmalloc(sizeof(struct snap), GFP_KERNEL)) == NULL)
                return -ENOMEM;
 
-       mbus = inode->u.generic_ip;
+       mbus = inode->i_private;
 
        sp->slen = snprintf(sp->str, STAT_BUF_SIZE,
            "nreaders %d events %u text_lost %u\n",
@@ -62,7 +62,7 @@ static int mon_stat_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-struct file_operations mon_fops_stat = {
+const struct file_operations mon_fops_stat = {
        .owner =        THIS_MODULE,
        .open =         mon_stat_open,
        .llseek =       no_llseek,
index f961a770cee2ea2a24d2ef01e39fd7d73fc99b0e..7a2346c53284b93a502b47b5911159f343a70ecc 100644 (file)
@@ -75,13 +75,13 @@ static void mon_text_ctor(void *, kmem_cache_t *, unsigned long);
  */
 
 static inline char mon_text_get_setup(struct mon_event_text *ep,
-    struct urb *urb, char ev_type)
+    struct urb *urb, char ev_type, struct mon_bus *mbus)
 {
 
        if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
                return '-';
 
-       if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
+       if (mbus->uses_dma && (urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
                return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
        if (urb->setup_packet == NULL)
                return 'Z';     /* '0' would be not as pretty. */
@@ -91,7 +91,7 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
 }
 
 static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
-    int len, char ev_type)
+    int len, char ev_type, struct mon_bus *mbus)
 {
        int pipe = urb->pipe;
 
@@ -117,7 +117,7 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
         * contain non-NULL garbage in case the upper level promised to
         * set DMA for the HCD.
         */
-       if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
+       if (mbus->uses_dma && (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
                return mon_dmapeek(ep->data, urb->transfer_dma, len);
 
        if (urb->transfer_buffer == NULL)
@@ -161,8 +161,9 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
        /* Collecting status makes debugging sense for submits, too */
        ep->status = urb->status;
 
-       ep->setup_flag = mon_text_get_setup(ep, urb, ev_type);
-       ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type);
+       ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus);
+       ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type,
+                       rp->r.m_bus);
 
        rp->nevents++;
        list_add_tail(&ep->e_link, &rp->e_list);
@@ -238,7 +239,7 @@ static int mon_text_open(struct inode *inode, struct file *file)
        int rc;
 
        mutex_lock(&mon_lock);
-       mbus = inode->u.generic_ip;
+       mbus = inode->i_private;
        ubus = mbus->u_bus;
 
        rp = kzalloc(sizeof(struct mon_reader_text), GFP_KERNEL);
@@ -401,7 +402,7 @@ static int mon_text_release(struct inode *inode, struct file *file)
        struct mon_event_text *ep;
 
        mutex_lock(&mon_lock);
-       mbus = inode->u.generic_ip;
+       mbus = inode->i_private;
 
        if (mbus->nreaders <= 0) {
                printk(KERN_ERR TAG ": consistency error on close\n");
@@ -435,7 +436,7 @@ static int mon_text_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-struct file_operations mon_fops_text = {
+const struct file_operations mon_fops_text = {
        .owner =        THIS_MODULE,
        .open =         mon_text_open,
        .llseek =       no_llseek,
index 33678c24ebeed5713b06a9eb1fd32d3283effc67..ab9d02d5df77a448c0c829c42b5b3633fbdfc054 100644 (file)
@@ -20,6 +20,7 @@ struct mon_bus {
        struct dentry *dent_s;          /* Debugging file */
        struct dentry *dent_t;          /* Text interface file */
        struct usb_bus *u_bus;
+       int uses_dma;
 
        /* Ref */
        int nreaders;                   /* Under mon_lock AND mbus->lock */
@@ -53,7 +54,7 @@ extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len);
 
 extern struct mutex mon_lock;
 
-extern struct file_operations mon_fops_text;
-extern struct file_operations mon_fops_stat;
+extern const struct file_operations mon_fops_text;
+extern const struct file_operations mon_fops_stat;
 
 #endif /* __USB_MON_H */
index 2e2bbc003e9392c7ae974b6ee62f86a1b287eb9d..9b97aa6384c795681de6830fc8a6d824a2c41411 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * ASIX AX8817X based USB 2.0 Ethernet Devices
- * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2003-2006 David Hollis <dhollis@davehollis.com>
  * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
+ * Copyright (C) 2006 James Painter <jamie.painter@iname.com>
  * Copyright (c) 2002-2003 TiVo Inc.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -36,6 +37,9 @@
 
 #include "usbnet.h"
 
+#define DRIVER_VERSION "14-Jun-2006"
+static const char driver_name [] = "asix";
+
 /* ASIX AX8817X based USB 2.0 Ethernet Devices */
 
 #define AX_CMD_SET_SW_MII              0x06
 #define AX_CMD_WRITE_EEPROM            0x0c
 #define AX_CMD_WRITE_ENABLE            0x0d
 #define AX_CMD_WRITE_DISABLE           0x0e
+#define AX_CMD_READ_RX_CTL             0x0f
 #define AX_CMD_WRITE_RX_CTL            0x10
 #define AX_CMD_READ_IPG012             0x11
 #define AX_CMD_WRITE_IPG0              0x12
 #define AX_CMD_WRITE_IPG1              0x13
+#define AX_CMD_READ_NODE_ID            0x13
 #define AX_CMD_WRITE_IPG2              0x14
 #define AX_CMD_WRITE_MULTI_FILTER      0x16
-#define AX_CMD_READ_NODE_ID            0x17
+#define AX88172_CMD_READ_NODE_ID       0x17
 #define AX_CMD_READ_PHY_ID             0x19
 #define AX_CMD_READ_MEDIUM_STATUS      0x1a
 #define AX_CMD_WRITE_MEDIUM_MODE       0x1b
 #define AX_CMD_READ_MONITOR_MODE       0x1c
 #define AX_CMD_WRITE_MONITOR_MODE      0x1d
+#define AX_CMD_READ_GPIOS              0x1e
 #define AX_CMD_WRITE_GPIOS             0x1f
 #define AX_CMD_SW_RESET                        0x20
 #define AX_CMD_SW_PHY_STATUS           0x21
 #define AX_CMD_SW_PHY_SELECT           0x22
-#define AX88772_CMD_READ_NODE_ID       0x13
 
 #define AX_MONITOR_MODE                        0x01
 #define AX_MONITOR_LINK                        0x02
 #define AX_MONITOR_HSFS                        0x10
 
 /* AX88172 Medium Status Register values */
-#define AX_MEDIUM_FULL_DUPLEX          0x02
-#define AX_MEDIUM_TX_ABORT_ALLOW       0x04
-#define AX_MEDIUM_FLOW_CONTROL_EN      0x10
+#define AX88172_MEDIUM_FD              0x02
+#define AX88172_MEDIUM_TX              0x04
+#define AX88172_MEDIUM_FC              0x10
+#define AX88172_MEDIUM_DEFAULT \
+               ( AX88172_MEDIUM_FD | AX88172_MEDIUM_TX | AX88172_MEDIUM_FC )
 
 #define AX_MCAST_FILTER_SIZE           8
 #define AX_MAX_MCAST                   64
 
-#define AX_EEPROM_LEN                  0x40
-
 #define AX_SWRESET_CLEAR               0x00
 #define AX_SWRESET_RR                  0x01
 #define AX_SWRESET_RT                  0x02
 #define AX88772_IPG1_DEFAULT           0x0c
 #define AX88772_IPG2_DEFAULT           0x12
 
-#define AX88772_MEDIUM_FULL_DUPLEX     0x0002
-#define AX88772_MEDIUM_RESERVED                0x0004
-#define AX88772_MEDIUM_RX_FC_ENABLE    0x0010
-#define AX88772_MEDIUM_TX_FC_ENABLE    0x0020
-#define AX88772_MEDIUM_PAUSE_FORMAT    0x0080
-#define AX88772_MEDIUM_RX_ENABLE       0x0100
-#define AX88772_MEDIUM_100MB           0x0200
-#define AX88772_MEDIUM_DEFAULT \
-       (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \
-        AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \
-        AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE )
+/* AX88772 & AX88178 Medium Mode Register */
+#define AX_MEDIUM_PF           0x0080
+#define AX_MEDIUM_JFE          0x0040
+#define AX_MEDIUM_TFC          0x0020
+#define AX_MEDIUM_RFC          0x0010
+#define AX_MEDIUM_ENCK         0x0008
+#define AX_MEDIUM_AC           0x0004
+#define AX_MEDIUM_FD           0x0002
+#define AX_MEDIUM_GM           0x0001
+#define AX_MEDIUM_SM           0x1000
+#define AX_MEDIUM_SBP          0x0800
+#define AX_MEDIUM_PS           0x0200
+#define AX_MEDIUM_RE           0x0100
+
+#define AX88178_MEDIUM_DEFAULT \
+       (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
+        AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
+        AX_MEDIUM_RE )
 
-#define AX_EEPROM_MAGIC                        0xdeadbeef
+#define AX88772_MEDIUM_DEFAULT \
+       (AX_MEDIUM_FD | AX_MEDIUM_RFC | \
+        AX_MEDIUM_TFC | AX_MEDIUM_PS | \
+        AX_MEDIUM_AC | AX_MEDIUM_RE )
+
+/* AX88772 & AX88178 RX_CTL values */
+#define AX_RX_CTL_SO                   0x0080
+#define AX_RX_CTL_AP                   0x0020
+#define AX_RX_CTL_AM                   0x0010
+#define AX_RX_CTL_AB                   0x0008
+#define AX_RX_CTL_SEP                  0x0004
+#define AX_RX_CTL_AMALL                        0x0002
+#define AX_RX_CTL_PRO                  0x0001
+#define AX_RX_CTL_MFB_2048             0x0000
+#define AX_RX_CTL_MFB_4096             0x0100
+#define AX_RX_CTL_MFB_8192             0x0200
+#define AX_RX_CTL_MFB_16384            0x0300
+
+#define AX_DEFAULT_RX_CTL      \
+       (AX_RX_CTL_SO | AX_RX_CTL_AB )
+
+/* GPIO 0 .. 2 toggles */
+#define AX_GPIO_GPO0EN         0x01    /* GPIO0 Output enable */
+#define AX_GPIO_GPO_0          0x02    /* GPIO0 Output value */
+#define AX_GPIO_GPO1EN         0x04    /* GPIO1 Output enable */
+#define AX_GPIO_GPO_1          0x08    /* GPIO1 Output value */
+#define AX_GPIO_GPO2EN         0x10    /* GPIO2 Output enable */
+#define AX_GPIO_GPO_2          0x20    /* GPIO2 Output value */
+#define AX_GPIO_RESERVED       0x40    /* Reserved */
+#define AX_GPIO_RSE            0x80    /* Reload serial EEPROM */
+
+#define AX_EEPROM_MAGIC                0xdeadbeef
+#define AX88172_EEPROM_LEN     0x40
+#define AX88772_EEPROM_LEN     0xff
+
+#define PHY_MODE_MARVELL       0x0000
+#define MII_MARVELL_LED_CTRL   0x0018
+#define MII_MARVELL_STATUS     0x001b
+#define MII_MARVELL_CTRL       0x0014
+
+#define MARVELL_LED_MANUAL     0x0019
+
+#define MARVELL_STATUS_HWCFG   0x0004
+
+#define MARVELL_CTRL_TXDELAY   0x0002
+#define MARVELL_CTRL_RXDELAY   0x0080
 
 /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
 struct asix_data {
        u8 multi_filter[AX_MCAST_FILTER_SIZE];
+       u8 phymode;
+       u8 ledmode;
+       u8 eeprom_len;
 };
 
 struct ax88172_int_data {
@@ -122,6 +183,8 @@ struct ax88172_int_data {
 static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
                            u16 size, void *data)
 {
+       devdbg(dev,"asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
+               cmd, value, index, size);
        return usb_control_msg(
                dev->udev,
                usb_rcvctrlpipe(dev->udev, 0),
@@ -137,6 +200,8 @@ static int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
 static int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
                             u16 size, void *data)
 {
+       devdbg(dev,"asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
+               cmd, value, index, size);
        return usb_control_msg(
                dev->udev,
                usb_sndctrlpipe(dev->udev, 0),
@@ -161,12 +226,167 @@ static void asix_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
        usb_free_urb(urb);
 }
 
+static void
+asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
+                                   u16 size, void *data)
+{
+       struct usb_ctrlrequest *req;
+       int status;
+       struct urb *urb;
+
+       devdbg(dev,"asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
+               cmd, value, index, size);
+       if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
+               deverr(dev, "Error allocating URB in write_cmd_async!");
+               return;
+       }
+
+       if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
+               deverr(dev, "Failed to allocate memory for control request");
+               usb_free_urb(urb);
+               return;
+       }
+
+       req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
+       req->bRequest = cmd;
+       req->wValue = value;
+       req->wIndex = index;
+       req->wLength = size;
+
+       usb_fill_control_urb(urb, dev->udev,
+                            usb_sndctrlpipe(dev->udev, 0),
+                            (void *)req, data, size,
+                            asix_async_cmd_callback, req);
+
+       if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+               deverr(dev, "Error submitting the control message: status=%d",
+                               status);
+               kfree(req);
+               usb_free_urb(urb);
+       }
+}
+
+static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+       u8  *head;
+       u32  header;
+       char *packet;
+       struct sk_buff *ax_skb;
+       u16 size;
+
+       head = (u8 *) skb->data;
+       memcpy(&header, head, sizeof(header));
+       le32_to_cpus(&header);
+       packet = head + sizeof(header);
+
+       skb_pull(skb, 4);
+
+       while (skb->len > 0) {
+               if ((short)(header & 0x0000ffff) !=
+                   ~((short)((header & 0xffff0000) >> 16))) {
+                       deverr(dev,"asix_rx_fixup() Bad Header Length");
+               }
+               /* get the packet length */
+               size = (u16) (header & 0x0000ffff);
+
+               if ((skb->len) - ((size + 1) & 0xfffe) == 0)
+                       return 2;
+               if (size > ETH_FRAME_LEN) {
+                       deverr(dev,"asix_rx_fixup() Bad RX Length %d", size);
+                       return 0;
+               }
+               ax_skb = skb_clone(skb, GFP_ATOMIC);
+               if (ax_skb) {
+                       ax_skb->len = size;
+                       ax_skb->data = packet;
+                       ax_skb->tail = packet + size;
+                       usbnet_skb_return(dev, ax_skb);
+               } else {
+                       return 0;
+               }
+
+               skb_pull(skb, (size + 1) & 0xfffe);
+
+               if (skb->len == 0)
+                       break;
+
+               head = (u8 *) skb->data;
+               memcpy(&header, head, sizeof(header));
+               le32_to_cpus(&header);
+               packet = head + sizeof(header);
+               skb_pull(skb, 4);
+       }
+
+       if (skb->len < 0) {
+               deverr(dev,"asix_rx_fixup() Bad SKB Length %d", skb->len);
+               return 0;
+       }
+       return 1;
+}
+
+static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+                                       gfp_t flags)
+{
+       int padlen;
+       int headroom = skb_headroom(skb);
+       int tailroom = skb_tailroom(skb);
+       u32 packet_len;
+       u32 padbytes = 0xffff0000;
+
+       padlen = ((skb->len + 4) % 512) ? 0 : 4;
+
+       if ((!skb_cloned(skb))
+           && ((headroom + tailroom) >= (4 + padlen))) {
+               if ((headroom < 4) || (tailroom < padlen)) {
+                       skb->data = memmove(skb->head + 4, skb->data, skb->len);
+                       skb->tail = skb->data + skb->len;
+               }
+       } else {
+               struct sk_buff *skb2;
+               skb2 = skb_copy_expand(skb, 4, padlen, flags);
+               dev_kfree_skb_any(skb);
+               skb = skb2;
+               if (!skb)
+                       return NULL;
+       }
+
+       skb_push(skb, 4);
+       packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+       memcpy(skb->data, &packet_len, sizeof(packet_len));
+
+       if ((skb->len % 512) == 0) {
+               memcpy( skb->tail, &padbytes, sizeof(padbytes));
+               skb_put(skb, sizeof(padbytes));
+       }
+       return skb;
+}
+
+static void asix_status(struct usbnet *dev, struct urb *urb)
+{
+       struct ax88172_int_data *event;
+       int link;
+
+       if (urb->actual_length < 8)
+               return;
+
+       event = urb->transfer_buffer;
+       link = event->link & 0x01;
+       if (netif_carrier_ok(dev->net) != link) {
+               if (link) {
+                       netif_carrier_on(dev->net);
+                       usbnet_defer_kevent (dev, EVENT_LINK_RESET );
+               } else
+                       netif_carrier_off(dev->net);
+               devdbg(dev, "Link Status is: %d", link);
+       }
+}
+
 static inline int asix_set_sw_mii(struct usbnet *dev)
 {
        int ret;
        ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
        if (ret < 0)
-               devdbg(dev, "Failed to enable software MII access");
+               deverr(dev, "Failed to enable software MII access");
        return ret;
 }
 
@@ -175,24 +395,27 @@ static inline int asix_set_hw_mii(struct usbnet *dev)
        int ret;
        ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
        if (ret < 0)
-               devdbg(dev, "Failed to enable hardware MII access");
+               deverr(dev, "Failed to enable hardware MII access");
        return ret;
 }
 
-static inline int asix_get_phyid(struct usbnet *dev)
+static inline int asix_get_phy_addr(struct usbnet *dev)
 {
        int ret = 0;
        void *buf;
 
+       devdbg(dev, "asix_get_phy_addr()");
+
        buf = kmalloc(2, GFP_KERNEL);
        if (!buf)
                goto out1;
 
        if ((ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID,
                                    0, 0, 2, buf)) < 2) {
-               devdbg(dev, "Error reading PHYID register: %02x", ret);
+               deverr(dev, "Error reading PHYID register: %02x", ret);
                goto out2;
        }
+       devdbg(dev, "asix_get_phy_addr() returning 0x%04x", *((u16 *)buf));
        ret = *((u8 *)buf + 1);
 out2:
        kfree(buf);
@@ -206,8 +429,29 @@ static int asix_sw_reset(struct usbnet *dev, u8 flags)
 
         ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
        if (ret < 0)
-               devdbg(dev,"Failed to send software reset: %02x", ret);
+               deverr(dev,"Failed to send software reset: %02x", ret);
+
+       return ret;
+}
 
+static u16 asix_read_rx_ctl(struct usbnet *dev)
+{
+       u16 ret = 0;
+       void *buf;
+
+       buf = kmalloc(2, GFP_KERNEL);
+       if (!buf)
+               goto out1;
+
+       if ((ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL,
+                                   0, 0, 2, buf)) < 2) {
+               deverr(dev, "Error reading RX_CTL register: %02x", ret);
+               goto out2;
+       }
+       ret = le16_to_cpu(*((u16 *)buf));
+out2:
+       kfree(buf);
+out1:
        return ret;
 }
 
@@ -215,82 +459,79 @@ static int asix_write_rx_ctl(struct usbnet *dev, u16 mode)
 {
        int ret;
 
+       devdbg(dev,"asix_write_rx_ctl() - mode = 0x%04x", mode);
        ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
        if (ret < 0)
-                devdbg(dev, "Failed to write RX_CTL mode: %02x", ret);
+               deverr(dev, "Failed to write RX_CTL mode to 0x%04x: %02x",
+                      mode, ret);
 
        return ret;
 }
 
-static void asix_status(struct usbnet *dev, struct urb *urb)
+static u16 asix_read_medium_status(struct usbnet *dev)
 {
-       struct ax88172_int_data *event;
-       int link;
+       u16 ret = 0;
+       void *buf;
 
-       if (urb->actual_length < 8)
-               return;
+       buf = kmalloc(2, GFP_KERNEL);
+       if (!buf)
+               goto out1;
 
-       event = urb->transfer_buffer;
-       link = event->link & 0x01;
-       if (netif_carrier_ok(dev->net) != link) {
-               if (link) {
-                       netif_carrier_on(dev->net);
-                       usbnet_defer_kevent (dev, EVENT_LINK_RESET );
-               } else
-                       netif_carrier_off(dev->net);
-               devdbg(dev, "Link Status is: %d", link);
+       if ((ret = asix_read_cmd(dev, AX_CMD_READ_MEDIUM_STATUS,
+                                   0, 0, 2, buf)) < 2) {
+               deverr(dev, "Error reading Medium Status register: %02x", ret);
+               goto out2;
        }
+       ret = le16_to_cpu(*((u16 *)buf));
+out2:
+       kfree(buf);
+out1:
+       return ret;
 }
 
-static void
-asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
-                                   u16 size, void *data)
+static int asix_write_medium_mode(struct usbnet *dev, u16 mode)
 {
-       struct usb_ctrlrequest *req;
-       int status;
-       struct urb *urb;
+       int ret;
 
-       if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) {
-               devdbg(dev, "Error allocating URB in write_cmd_async!");
-               return;
-       }
+       devdbg(dev,"asix_write_medium_mode() - mode = 0x%04x", mode);
+       ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+       if (ret < 0)
+               deverr(dev, "Failed to write Medium Mode mode to 0x%04x: %02x",
+                       mode, ret);
 
-       if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) {
-               deverr(dev, "Failed to allocate memory for control request");
-               usb_free_urb(urb);
-               return;
-       }
+       return ret;
+}
 
-       req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-       req->bRequest = cmd;
-       req->wValue = cpu_to_le16(value);
-       req->wIndex = cpu_to_le16(index);
-       req->wLength = cpu_to_le16(size);
+static int asix_write_gpio(struct usbnet *dev, u16 value, int sleep)
+{
+       int ret;
 
-       usb_fill_control_urb(urb, dev->udev,
-                            usb_sndctrlpipe(dev->udev, 0),
-                            (void *)req, data, size,
-                            asix_async_cmd_callback, req);
+       devdbg(dev,"asix_write_gpio() - value = 0x%04x", value);
+       ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL);
+       if (ret < 0)
+               deverr(dev, "Failed to write GPIO value 0x%04x: %02x",
+                       value, ret);
 
-       if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
-               deverr(dev, "Error submitting the control message: status=%d",
-                               status);
-               kfree(req);
-               usb_free_urb(urb);
-       }
+       if (sleep)
+               msleep(sleep);
+
+       return ret;
 }
 
+/*
+ * AX88772 & AX88178 have a 16-bit RX_CTL value
+ */
 static void asix_set_multicast(struct net_device *net)
 {
        struct usbnet *dev = netdev_priv(net);
        struct asix_data *data = (struct asix_data *)&dev->data;
-       u8 rx_ctl = 0x8c;
+       u16 rx_ctl = AX_DEFAULT_RX_CTL;
 
        if (net->flags & IFF_PROMISC) {
-               rx_ctl |= 0x01;
+               rx_ctl |= AX_RX_CTL_PRO;
        } else if (net->flags & IFF_ALLMULTI
                   || net->mc_count > AX_MAX_MCAST) {
-               rx_ctl |= 0x02;
+               rx_ctl |= AX_RX_CTL_AMALL;
        } else if (net->mc_count == 0) {
                /* just broadcast and directed */
        } else {
@@ -317,7 +558,7 @@ static void asix_set_multicast(struct net_device *net)
                asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
                                   AX_MCAST_FILTER_SIZE, data->multi_filter);
 
-               rx_ctl |= 0x10;
+               rx_ctl |= AX_RX_CTL_AM;
        }
 
        asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
@@ -333,50 +574,43 @@ static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
                                (__u16)loc, 2, (u16 *)&res);
        asix_set_hw_mii(dev);
 
-       return res & 0xffff;
-}
+       devdbg(dev, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", phy_id, loc, le16_to_cpu(res & 0xffff));
 
-/* same as above, but converts resulting value to cpu byte order */
-static int asix_mdio_read_le(struct net_device *netdev, int phy_id, int loc)
-{
-       return le16_to_cpu(asix_mdio_read(netdev,phy_id, loc));
+       return le16_to_cpu(res & 0xffff);
 }
 
 static void
 asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val)
 {
        struct usbnet *dev = netdev_priv(netdev);
-       u16 res = val;
+       u16 res = cpu_to_le16(val);
 
+       devdbg(dev, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", phy_id, loc, val);
        asix_set_sw_mii(dev);
        asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id,
                                (__u16)loc, 2, (u16 *)&res);
        asix_set_hw_mii(dev);
 }
 
-/* same as above, but converts new value to le16 byte order before writing */
-static void
-asix_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val)
+/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
+static u32 asix_get_phyid(struct usbnet *dev)
 {
-       asix_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) );
-}
+       int phy_reg;
+       u32 phy_id;
 
-static int ax88172_link_reset(struct usbnet *dev)
-{
-       u16 lpa;
-       u16 adv;
-       u16 res;
-       u8 mode;
+       phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
+       if (phy_reg < 0)
+               return 0;
 
-       mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
-       lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
-       adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
-       res = mii_nway_result(lpa|adv);
-       if (res & LPA_DUPLEX)
-               mode |= AX_MEDIUM_FULL_DUPLEX;
-       asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+       phy_id = (phy_reg & 0xffff) << 16;
 
-       return 0;
+       phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2);
+       if (phy_reg < 0)
+               return 0;
+
+       phy_id |= (phy_reg & 0xffff);
+
+       return phy_id;
 }
 
 static void
@@ -423,7 +657,10 @@ asix_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo)
 
 static int asix_get_eeprom_len(struct net_device *net)
 {
-       return AX_EEPROM_LEN;
+       struct usbnet *dev = netdev_priv(net);
+       struct asix_data *data = (struct asix_data *)&dev->data;
+
+       return data->eeprom_len;
 }
 
 static int asix_get_eeprom(struct net_device *net,
@@ -453,9 +690,14 @@ static int asix_get_eeprom(struct net_device *net,
 static void asix_get_drvinfo (struct net_device *net,
                                 struct ethtool_drvinfo *info)
 {
+       struct usbnet *dev = netdev_priv(net);
+       struct asix_data *data = (struct asix_data *)&dev->data;
+
        /* Inherit standard device info */
        usbnet_get_drvinfo(net, info);
-       info->eedump_len = 0x3e;
+       strncpy (info->driver, driver_name, sizeof info->driver);
+       strncpy (info->version, DRIVER_VERSION, sizeof info->version);
+       info->eedump_len = data->eeprom_len;
 }
 
 static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
@@ -468,17 +710,44 @@ static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd)
 static int asix_set_settings(struct net_device *net, struct ethtool_cmd *cmd)
 {
        struct usbnet *dev = netdev_priv(net);
+       int res = mii_ethtool_sset(&dev->mii,cmd);
+
+       /* link speed/duplex might have changed */
+       if (dev->driver_info->link_reset)
+               dev->driver_info->link_reset(dev);
 
-       return mii_ethtool_sset(&dev->mii,cmd);
+       return res;
 }
 
-/* We need to override some ethtool_ops so we require our
-   own structure so we don't interfere with other usbnet
-   devices that may be connected at the same time. */
-static struct ethtool_ops ax88172_ethtool_ops = {
-       .get_drvinfo            = asix_get_drvinfo,
-       .get_link               = ethtool_op_get_link,
-       .get_msglevel           = usbnet_get_msglevel,
+static int asix_nway_reset(struct net_device *net)
+{
+       struct usbnet *dev = netdev_priv(net);
+
+       return mii_nway_restart(&dev->mii);
+}
+
+static u32 asix_get_link(struct net_device *net)
+{
+       struct usbnet *dev = netdev_priv(net);
+
+       return mii_link_ok(&dev->mii);
+}
+
+static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+{
+       struct usbnet *dev = netdev_priv(net);
+
+       return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+}
+
+/* We need to override some ethtool_ops so we require our
+   own structure so we don't interfere with other usbnet
+   devices that may be connected at the same time. */
+static struct ethtool_ops ax88172_ethtool_ops = {
+       .get_drvinfo            = asix_get_drvinfo,
+       .get_link               = asix_get_link,
+       .nway_reset             = asix_nway_reset,
+       .get_msglevel           = usbnet_get_msglevel,
        .set_msglevel           = usbnet_set_msglevel,
        .get_wol                = asix_get_wol,
        .set_wol                = asix_set_wol,
@@ -488,11 +757,66 @@ static struct ethtool_ops ax88172_ethtool_ops = {
        .set_settings           = asix_set_settings,
 };
 
-static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd)
+static void ax88172_set_multicast(struct net_device *net)
 {
        struct usbnet *dev = netdev_priv(net);
+       struct asix_data *data = (struct asix_data *)&dev->data;
+       u8 rx_ctl = 0x8c;
 
-       return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+       if (net->flags & IFF_PROMISC) {
+               rx_ctl |= 0x01;
+       } else if (net->flags & IFF_ALLMULTI
+                  || net->mc_count > AX_MAX_MCAST) {
+               rx_ctl |= 0x02;
+       } else if (net->mc_count == 0) {
+               /* just broadcast and directed */
+       } else {
+               /* We use the 20 byte dev->data
+                * for our 8 byte filter buffer
+                * to avoid allocating memory that
+                * is tricky to free later */
+               struct dev_mc_list *mc_list = net->mc_list;
+               u32 crc_bits;
+               int i;
+
+               memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE);
+
+               /* Build the multicast hash filter. */
+               for (i = 0; i < net->mc_count; i++) {
+                       crc_bits =
+                           ether_crc(ETH_ALEN,
+                                     mc_list->dmi_addr) >> 26;
+                       data->multi_filter[crc_bits >> 3] |=
+                           1 << (crc_bits & 7);
+                       mc_list = mc_list->next;
+               }
+
+               asix_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0,
+                                  AX_MCAST_FILTER_SIZE, data->multi_filter);
+
+               rx_ctl |= 0x10;
+       }
+
+       asix_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL);
+}
+
+static int ax88172_link_reset(struct usbnet *dev)
+{
+       u8 mode;
+       struct ethtool_cmd ecmd;
+
+       mii_check_media(&dev->mii, 1, 1);
+       mii_ethtool_gset(&dev->mii, &ecmd);
+       mode = AX88172_MEDIUM_DEFAULT;
+
+       if (ecmd.duplex != DUPLEX_FULL)
+               mode |= ~AX88172_MEDIUM_FD;
+
+       devdbg(dev, "ax88172_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode);
+
+       asix_write_medium_mode(dev, mode);
+
+       return 0;
 }
 
 static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
@@ -501,6 +825,9 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
        void *buf;
        int i;
        unsigned long gpio_bits = dev->driver_info->data;
+       struct asix_data *data = (struct asix_data *)&dev->data;
+
+       data->eeprom_len = AX88172_EEPROM_LEN;
 
        usbnet_get_endpoints(dev,intf);
 
@@ -519,12 +846,12 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
                msleep(5);
        }
 
-       if ((ret = asix_write_rx_ctl(dev,0x80)) < 0)
+       if ((ret = asix_write_rx_ctl(dev, 0x80)) < 0)
                goto out2;
 
        /* Get the MAC address */
        memset(buf, 0, ETH_ALEN);
-       if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
+       if ((ret = asix_read_cmd(dev, AX88172_CMD_READ_NODE_ID,
                                0, 0, 6, buf)) < 0) {
                dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
                goto out2;
@@ -537,14 +864,14 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->mii.mdio_write = asix_mdio_write;
        dev->mii.phy_id_mask = 0x3f;
        dev->mii.reg_num_mask = 0x1f;
-       dev->mii.phy_id = asix_get_phyid(dev);
+       dev->mii.phy_id = asix_get_phy_addr(dev);
        dev->net->do_ioctl = asix_ioctl;
 
-       dev->net->set_multicast_list = asix_set_multicast;
+       dev->net->set_multicast_list = ax88172_set_multicast;
        dev->net->ethtool_ops = &ax88172_ethtool_ops;
 
-       asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-       asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
                ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
        mii_nway_restart(&dev->mii);
 
@@ -557,7 +884,8 @@ out1:
 
 static struct ethtool_ops ax88772_ethtool_ops = {
        .get_drvinfo            = asix_get_drvinfo,
-       .get_link               = ethtool_op_get_link,
+       .get_link               = asix_get_link,
+       .nway_reset             = asix_nway_reset,
        .get_msglevel           = usbnet_get_msglevel,
        .set_msglevel           = usbnet_set_msglevel,
        .get_wol                = asix_get_wol,
@@ -568,10 +896,37 @@ static struct ethtool_ops ax88772_ethtool_ops = {
        .set_settings           = asix_set_settings,
 };
 
+static int ax88772_link_reset(struct usbnet *dev)
+{
+       u16 mode;
+       struct ethtool_cmd ecmd;
+
+       mii_check_media(&dev->mii, 1, 1);
+       mii_ethtool_gset(&dev->mii, &ecmd);
+       mode = AX88772_MEDIUM_DEFAULT;
+
+       if (ecmd.speed != SPEED_100)
+               mode &= ~AX_MEDIUM_PS;
+
+       if (ecmd.duplex != DUPLEX_FULL)
+               mode &= ~AX_MEDIUM_FD;
+
+       devdbg(dev, "ax88772_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode);
+
+       asix_write_medium_mode(dev, mode);
+
+       return 0;
+}
+
 static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 {
        int ret;
        void *buf;
+       u16 rx_ctl;
+       struct asix_data *data = (struct asix_data *)&dev->data;
+       u32 phyid;
+
+       data->eeprom_len = AX88772_EEPROM_LEN;
 
        usbnet_get_endpoints(dev,intf);
 
@@ -582,13 +937,12 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                goto out1;
        }
 
-       if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS,
-                                    0x00B0, 0, 0, buf)) < 0)
+       if ((ret = asix_write_gpio(dev,
+                       AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0)
                goto out2;
 
-       msleep(5);
        if ((ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
-                               0x0001, 0, 0, buf)) < 0) {
+                               0x0000, 0, 0, buf)) < 0) {
                dbg("Select PHY #1 failed: %d", ret);
                goto out2;
        }
@@ -605,36 +959,34 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                goto out2;
 
        msleep(150);
-       if ((ret = asix_write_rx_ctl(dev, 0x00)) < 0)
+       rx_ctl = asix_read_rx_ctl(dev);
+       dbg("RX_CTL is 0x%04x after software reset", rx_ctl);
+       if ((ret = asix_write_rx_ctl(dev, 0x0000)) < 0)
                goto out2;
 
+       rx_ctl = asix_read_rx_ctl(dev);
+       dbg("RX_CTL is 0x%04x setting to 0x0000", rx_ctl);
+
        /* Get the MAC address */
        memset(buf, 0, ETH_ALEN);
-       if ((ret = asix_read_cmd(dev, AX88772_CMD_READ_NODE_ID,
+       if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
                                0, 0, ETH_ALEN, buf)) < 0) {
                dbg("Failed to read MAC address: %d", ret);
                goto out2;
        }
        memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 
-       if ((ret = asix_set_sw_mii(dev)) < 0)
-               goto out2;
-
-       if (((ret = asix_read_cmd(dev, AX_CMD_READ_MII_REG,
-                               0x0010, 2, 2, buf)) < 0)
-                       || (*((u16 *)buf) != 0x003b)) {
-               dbg("Read PHY register 2 must be 0x3b00: %d", ret);
-               goto out2;
-       }
-
        /* Initialize MII structure */
        dev->mii.dev = dev->net;
        dev->mii.mdio_read = asix_mdio_read;
        dev->mii.mdio_write = asix_mdio_write;
-       dev->mii.phy_id_mask = 0xff;
-       dev->mii.reg_num_mask = 0xff;
+       dev->mii.phy_id_mask = 0x1f;
+       dev->mii.reg_num_mask = 0x1f;
        dev->net->do_ioctl = asix_ioctl;
-       dev->mii.phy_id = asix_get_phyid(dev);
+       dev->mii.phy_id = asix_get_phy_addr(dev);
+
+       phyid = asix_get_phyid(dev);
+       dbg("PHYID=0x%08x", phyid);
 
        if ((ret = asix_sw_reset(dev, AX_SWRESET_PRL)) < 0)
                goto out2;
@@ -649,16 +1001,13 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->set_multicast_list = asix_set_multicast;
        dev->net->ethtool_ops = &ax88772_ethtool_ops;
 
-       asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
-       asix_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
                        ADVERTISE_ALL | ADVERTISE_CSMA);
        mii_nway_restart(&dev->mii);
 
-       if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
-                               AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
-               dbg("Write medium mode register: %d", ret);
+       if ((ret = asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT)) < 0)
                goto out2;
-       }
 
        if ((ret = asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
                                AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
@@ -666,13 +1015,17 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
                goto out2;
        }
-       if ((ret = asix_set_hw_mii(dev)) < 0)
-               goto out2;
 
        /* Set RX_CTL to default values with 2k buffer, and enable cactus */
-       if ((ret = asix_write_rx_ctl(dev, 0x0088)) < 0)
+       if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0)
                goto out2;
 
+       rx_ctl = asix_read_rx_ctl(dev);
+       dbg("RX_CTL is 0x%04x after all initializations", rx_ctl);
+
+       rx_ctl = asix_read_medium_status(dev);
+       dbg("Medium Status is 0x%04x after all initializations", rx_ctl);
+
        kfree(buf);
 
        /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
@@ -690,120 +1043,285 @@ out1:
        return ret;
 }
 
-static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+static struct ethtool_ops ax88178_ethtool_ops = {
+       .get_drvinfo            = asix_get_drvinfo,
+       .get_link               = asix_get_link,
+       .nway_reset             = asix_nway_reset,
+       .get_msglevel           = usbnet_get_msglevel,
+       .set_msglevel           = usbnet_set_msglevel,
+       .get_wol                = asix_get_wol,
+       .set_wol                = asix_set_wol,
+       .get_eeprom_len         = asix_get_eeprom_len,
+       .get_eeprom             = asix_get_eeprom,
+       .get_settings           = asix_get_settings,
+       .set_settings           = asix_set_settings,
+};
+
+static int marvell_phy_init(struct usbnet *dev)
 {
-       u8  *head;
-       u32  header;
-       char *packet;
-       struct sk_buff *ax_skb;
-       u16 size;
+       struct asix_data *data = (struct asix_data *)&dev->data;
+       u16 reg;
 
-       head = (u8 *) skb->data;
-       memcpy(&header, head, sizeof(header));
-       le32_to_cpus(&header);
-       packet = head + sizeof(header);
+       devdbg(dev,"marvell_phy_init()");
 
-       skb_pull(skb, 4);
+       reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_MARVELL_STATUS);
+       devdbg(dev,"MII_MARVELL_STATUS = 0x%04x", reg);
 
-       while (skb->len > 0) {
-               if ((short)(header & 0x0000ffff) !=
-                   ~((short)((header & 0xffff0000) >> 16))) {
-                       devdbg(dev,"header length data is error");
-               }
-               /* get the packet length */
-               size = (u16) (header & 0x0000ffff);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_MARVELL_CTRL,
+                       MARVELL_CTRL_RXDELAY | MARVELL_CTRL_TXDELAY);
 
-               if ((skb->len) - ((size + 1) & 0xfffe) == 0)
-                       return 2;
-               if (size > ETH_FRAME_LEN) {
-                       devdbg(dev,"invalid rx length %d", size);
-                       return 0;
-               }
-               ax_skb = skb_clone(skb, GFP_ATOMIC);
-               if (ax_skb) {
-                       ax_skb->len = size;
-                       ax_skb->data = packet;
-                       ax_skb->tail = packet + size;
-                       usbnet_skb_return(dev, ax_skb);
-               } else {
-                       return 0;
-               }
+       if (data->ledmode) {
+               reg = asix_mdio_read(dev->net, dev->mii.phy_id,
+                       MII_MARVELL_LED_CTRL);
+               devdbg(dev,"MII_MARVELL_LED_CTRL (1) = 0x%04x", reg);
 
-               skb_pull(skb, (size + 1) & 0xfffe);
+               reg &= 0xf8ff;
+               reg |= (1 + 0x0100);
+               asix_mdio_write(dev->net, dev->mii.phy_id,
+                       MII_MARVELL_LED_CTRL, reg);
 
-               if (skb->len == 0)
-                       break;
+               reg = asix_mdio_read(dev->net, dev->mii.phy_id,
+                       MII_MARVELL_LED_CTRL);
+               devdbg(dev,"MII_MARVELL_LED_CTRL (2) = 0x%04x", reg);
+               reg &= 0xfc0f;
+       }
 
-               head = (u8 *) skb->data;
-               memcpy(&header, head, sizeof(header));
-               le32_to_cpus(&header);
-               packet = head + sizeof(header);
-               skb_pull(skb, 4);
+       return 0;
+}
+
+static int marvell_led_status(struct usbnet *dev, u16 speed)
+{
+       u16 reg = asix_mdio_read(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL);
+
+       devdbg(dev, "marvell_led_status() read 0x%04x", reg);
+
+       /* Clear out the center LED bits - 0x03F0 */
+       reg &= 0xfc0f;
+
+       switch (speed) {
+               case SPEED_1000:
+                       reg |= 0x03e0;
+                       break;
+               case SPEED_100:
+                       reg |= 0x03b0;
+                       break;
+               default:
+                       reg |= 0x02f0;
        }
 
-       if (skb->len < 0) {
-               devdbg(dev,"invalid rx length %d", skb->len);
-               return 0;
+       devdbg(dev, "marvell_led_status() writing 0x%04x", reg);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MARVELL_LED_MANUAL, reg);
+
+       return 0;
+}
+
+static int ax88178_link_reset(struct usbnet *dev)
+{
+       u16 mode;
+       struct ethtool_cmd ecmd;
+       struct asix_data *data = (struct asix_data *)&dev->data;
+
+       devdbg(dev,"ax88178_link_reset()");
+
+       mii_check_media(&dev->mii, 1, 1);
+       mii_ethtool_gset(&dev->mii, &ecmd);
+       mode = AX88178_MEDIUM_DEFAULT;
+
+       if (ecmd.speed == SPEED_1000)
+               mode |= AX_MEDIUM_GM | AX_MEDIUM_ENCK;
+       else if (ecmd.speed == SPEED_100)
+               mode |= AX_MEDIUM_PS;
+       else
+               mode &= ~(AX_MEDIUM_PS | AX_MEDIUM_GM);
+
+       if (ecmd.duplex == DUPLEX_FULL)
+               mode |= AX_MEDIUM_FD;
+       else
+               mode &= ~AX_MEDIUM_FD;
+
+       devdbg(dev, "ax88178_link_reset() speed: %d duplex: %d setting mode to 0x%04x", ecmd.speed, ecmd.duplex, mode);
+
+       asix_write_medium_mode(dev, mode);
+
+       if (data->phymode == PHY_MODE_MARVELL && data->ledmode)
+               marvell_led_status(dev, ecmd.speed);
+
+       return 0;
+}
+
+static void ax88178_set_mfb(struct usbnet *dev)
+{
+       u16 mfb = AX_RX_CTL_MFB_16384;
+       u16 rxctl;
+       u16 medium;
+       int old_rx_urb_size = dev->rx_urb_size;
+
+       if (dev->hard_mtu < 2048) {
+               dev->rx_urb_size = 2048;
+               mfb = AX_RX_CTL_MFB_2048;
+       } else if (dev->hard_mtu < 4096) {
+               dev->rx_urb_size = 4096;
+               mfb = AX_RX_CTL_MFB_4096;
+       } else if (dev->hard_mtu < 8192) {
+               dev->rx_urb_size = 8192;
+               mfb = AX_RX_CTL_MFB_8192;
+       } else if (dev->hard_mtu < 16384) {
+               dev->rx_urb_size = 16384;
+               mfb = AX_RX_CTL_MFB_16384;
        }
-       return 1;
+
+       rxctl = asix_read_rx_ctl(dev);
+       asix_write_rx_ctl(dev, (rxctl & ~AX_RX_CTL_MFB_16384) | mfb);
+
+       medium = asix_read_medium_status(dev);
+       if (dev->net->mtu > 1500)
+               medium |= AX_MEDIUM_JFE;
+       else
+               medium &= ~AX_MEDIUM_JFE;
+       asix_write_medium_mode(dev, medium);
+
+       if (dev->rx_urb_size > old_rx_urb_size)
+               usbnet_unlink_rx_urbs(dev);
 }
 
-static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
-                                       gfp_t flags)
+static int ax88178_change_mtu(struct net_device *net, int new_mtu)
 {
-       int padlen;
-       int headroom = skb_headroom(skb);
-       int tailroom = skb_tailroom(skb);
-       u32 packet_len;
-       u32 padbytes = 0xffff0000;
+       struct usbnet *dev = netdev_priv(net);
+       int ll_mtu = new_mtu + net->hard_header_len + 4;
 
-       padlen = ((skb->len + 4) % 512) ? 0 : 4;
+       devdbg(dev, "ax88178_change_mtu() new_mtu=%d", new_mtu);
 
-       if ((!skb_cloned(skb))
-           && ((headroom + tailroom) >= (4 + padlen))) {
-               if ((headroom < 4) || (tailroom < padlen)) {
-                       skb->data = memmove(skb->head + 4, skb->data, skb->len);
-                       skb->tail = skb->data + skb->len;
-               }
+       if (new_mtu <= 0 || ll_mtu > 16384)
+               return -EINVAL;
+
+       if ((ll_mtu % dev->maxpacket) == 0)
+               return -EDOM;
+
+       net->mtu = new_mtu;
+       dev->hard_mtu = net->mtu + net->hard_header_len;
+       ax88178_set_mfb(dev);
+
+       return 0;
+}
+
+static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       struct asix_data *data = (struct asix_data *)&dev->data;
+       int ret;
+       void *buf;
+       u16 eeprom;
+       int gpio0 = 0;
+       u32 phyid;
+
+       usbnet_get_endpoints(dev,intf);
+
+       buf = kmalloc(6, GFP_KERNEL);
+       if(!buf) {
+               dbg ("Cannot allocate memory for buffer");
+               ret = -ENOMEM;
+               goto out1;
+       }
+
+       eeprom = 0;
+       asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &eeprom);
+       dbg("GPIO Status: 0x%04x", eeprom);
+
+       asix_write_cmd(dev, AX_CMD_WRITE_ENABLE, 0, 0, 0, NULL);
+       asix_read_cmd(dev, AX_CMD_READ_EEPROM, 0x0017, 0, 2, &eeprom);
+       asix_write_cmd(dev, AX_CMD_WRITE_DISABLE, 0, 0, 0, NULL);
+
+       dbg("EEPROM index 0x17 is 0x%04x", eeprom);
+
+       if (eeprom == 0xffff) {
+               data->phymode = PHY_MODE_MARVELL;
+               data->ledmode = 0;
+               gpio0 = 1;
        } else {
-               struct sk_buff *skb2;
-               skb2 = skb_copy_expand(skb, 4, padlen, flags);
-               dev_kfree_skb_any(skb);
-               skb = skb2;
-               if (!skb)
-                       return NULL;
+               data->phymode = eeprom & 7;
+               data->ledmode = eeprom >> 8;
+               gpio0 = (eeprom & 0x80) ? 0 : 1;
        }
+       dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode);
 
-       skb_push(skb, 4);
-       packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
-       memcpy(skb->data, &packet_len, sizeof(packet_len));
+       asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40);
+       if ((eeprom >> 8) != 1) {
+               asix_write_gpio(dev, 0x003c, 30);
+               asix_write_gpio(dev, 0x001c, 300);
+               asix_write_gpio(dev, 0x003c, 30);
+       } else {
+               dbg("gpio phymode == 1 path");
+               asix_write_gpio(dev, AX_GPIO_GPO1EN, 30);
+               asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30);
+       }
 
-       if ((skb->len % 512) == 0) {
-               memcpy( skb->tail, &padbytes, sizeof(padbytes));
-               skb_put(skb, sizeof(padbytes));
+       asix_sw_reset(dev, 0);
+       msleep(150);
+
+       asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD);
+       msleep(150);
+
+       asix_write_rx_ctl(dev, 0);
+
+       /* Get the MAC address */
+       memset(buf, 0, ETH_ALEN);
+       if ((ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
+                               0, 0, ETH_ALEN, buf)) < 0) {
+               dbg("Failed to read MAC address: %d", ret);
+               goto out2;
        }
-       return skb;
-}
+       memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 
-static int ax88772_link_reset(struct usbnet *dev)
-{
-       u16 lpa;
-       u16 adv;
-       u16 res;
-       u16 mode;
+       /* Initialize MII structure */
+       dev->mii.dev = dev->net;
+       dev->mii.mdio_read = asix_mdio_read;
+       dev->mii.mdio_write = asix_mdio_write;
+       dev->mii.phy_id_mask = 0x1f;
+       dev->mii.reg_num_mask = 0xff;
+       dev->mii.supports_gmii = 1;
+       dev->net->do_ioctl = asix_ioctl;
+       dev->mii.phy_id = asix_get_phy_addr(dev);
+       dev->net->set_multicast_list = asix_set_multicast;
+       dev->net->ethtool_ops = &ax88178_ethtool_ops;
+       dev->net->change_mtu = &ax88178_change_mtu;
 
-       mode = AX88772_MEDIUM_DEFAULT;
-       lpa = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA);
-       adv = asix_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE);
-       res = mii_nway_result(lpa|adv);
+       phyid = asix_get_phyid(dev);
+       dbg("PHYID=0x%08x", phyid);
 
-       if ((res & LPA_DUPLEX) == 0)
-               mode &= ~AX88772_MEDIUM_FULL_DUPLEX;
-       if ((res & LPA_100) == 0)
-               mode &= ~AX88772_MEDIUM_100MB;
-       asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
+       if (data->phymode == PHY_MODE_MARVELL) {
+               marvell_phy_init(dev);
+               msleep(60);
+       }
+
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
+                       BMCR_RESET | BMCR_ANENABLE);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+                       ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
+       asix_mdio_write(dev->net, dev->mii.phy_id, MII_CTRL1000,
+                       ADVERTISE_1000FULL);
+
+       mii_nway_restart(&dev->mii);
+
+       if ((ret = asix_write_medium_mode(dev, AX88178_MEDIUM_DEFAULT)) < 0)
+               goto out2;
+
+       if ((ret = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) < 0)
+               goto out2;
+
+       kfree(buf);
+
+       /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
+       if (dev->driver_info->flags & FLAG_FRAMING_AX) {
+               /* hard_mtu  is still the default - the device does not support
+                  jumbo eth frames */
+               dev->rx_urb_size = 2048;
+       }
 
        return 0;
+
+out2:
+       kfree(buf);
+out1:
+       return ret;
 }
 
 static const struct driver_info ax8817x_info = {
@@ -853,8 +1371,19 @@ static const struct driver_info ax88772_info = {
        .link_reset = ax88772_link_reset,
        .reset = ax88772_link_reset,
        .flags = FLAG_ETHER | FLAG_FRAMING_AX,
-       .rx_fixup = ax88772_rx_fixup,
-       .tx_fixup = ax88772_tx_fixup,
+       .rx_fixup = asix_rx_fixup,
+       .tx_fixup = asix_tx_fixup,
+};
+
+static const struct driver_info ax88178_info = {
+       .description = "ASIX AX88178 USB 2.0 Ethernet",
+       .bind = ax88178_bind,
+       .status = asix_status,
+       .link_reset = ax88178_link_reset,
+       .reset = ax88178_link_reset,
+       .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+       .rx_fixup = asix_rx_fixup,
+       .tx_fixup = asix_tx_fixup,
 };
 
 static const struct usb_device_id      products [] = {
@@ -913,7 +1442,7 @@ static const struct usb_device_id  products [] = {
 }, {
        // ASIX AX88178 10/100/1000
        USB_DEVICE (0x0b95, 0x1780),
-       .driver_info = (unsigned long) &ax88772_info,
+       .driver_info = (unsigned long) &ax88178_info,
 }, {
        // Linksys USB200M Rev 2
        USB_DEVICE (0x13b1, 0x0018),
@@ -922,6 +1451,14 @@ static const struct usb_device_id products [] = {
        // 0Q0 cable ethernet
        USB_DEVICE (0x1557, 0x7720),
        .driver_info = (unsigned long) &ax88772_info,
+}, {
+       // DLink DUB-E100 H/W Ver B1
+       USB_DEVICE (0x07d1, 0x3c05),
+       .driver_info = (unsigned long) &ax88772_info,
+}, {
+       // Linksys USB1000
+       USB_DEVICE (0x1737, 0x0039),
+       .driver_info = (unsigned long) &ax88178_info,
 },
        { },            // END
 };
index a9b6eeac3e3fa5da89949bca70990f2258c3e279..301baa72bac7b4ed20859a4fe64b97dfd545a9b4 100644 (file)
@@ -498,25 +498,24 @@ static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 static struct sk_buff *
 net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
 {
-       int                     padlen;
        struct sk_buff          *skb2;
        struct nc_header        *header = NULL;
        struct nc_trailer       *trailer = NULL;
+       int                     padlen = sizeof (struct nc_trailer);
        int                     len = skb->len;
 
-       padlen = ((len + sizeof (struct nc_header)
-                       + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1;
+       if (!((len + padlen + sizeof (struct nc_header)) & 0x01))
+               padlen++;
        if (!skb_cloned(skb)) {
                int     headroom = skb_headroom(skb);
                int     tailroom = skb_tailroom(skb);
 
-               if ((padlen + sizeof (struct nc_trailer)) <= tailroom
-                           && sizeof (struct nc_header) <= headroom)
+               if (padlen <= tailroom &&
+                   sizeof(struct nc_header) <= headroom)
                        /* There's enough head and tail room */
                        goto encapsulate;
 
-               if ((sizeof (struct nc_header) + padlen
-                                       + sizeof (struct nc_trailer)) <
+               if ((sizeof (struct nc_header) + padlen) <
                                (headroom + tailroom)) {
                        /* There's enough total room, so just readjust */
                        skb->data = memmove(skb->head
@@ -530,7 +529,7 @@ net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
        /* Create a new skb to use with the correct size */
        skb2 = skb_copy_expand(skb,
                                sizeof (struct nc_header),
-                               sizeof (struct nc_trailer) + padlen,
+                               padlen,
                                flags);
        dev_kfree_skb_any(skb);
        if (!skb2)
index ab21f960d255f250c01f43912744103ab73cd03f..b8e25af13f023ed8e5c9c6b115f05b28a2ce45c2 100644 (file)
@@ -619,7 +619,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
        switch (urb->status) {
        case 0:
                break;
-       case -ETIMEDOUT:
+       case -ETIME:
                if (netif_msg_rx_err(pegasus))
                        pr_debug("%s: reset MAC\n", net->name);
                pegasus->flags &= ~PEGASUS_RX_BUSY;
index a72685b96061dfb862a85aa8368e7758ce227089..2364c20993874f381c4975430000a56fb8a4a9a4 100644 (file)
@@ -438,7 +438,7 @@ static void read_bulk_callback(struct urb *urb, struct pt_regs *regs)
                break;
        case -ENOENT:
                return; /* the urb is in unlink state */
-       case -ETIMEDOUT:
+       case -ETIME:
                warn("may be reset is needed?..");
                goto goon;
        default:
index 54183e173a6d9a071b30609ab744490b08061243..98a522f1e264412bc7b15971aee924125930eedd 100644 (file)
  * let the USB host controller be busy for 5msec or more before an irq
  * is required, under load.  Jumbograms change the equation.
  */
-#define        RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
-#define        TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4)
+#define RX_MAX_QUEUE_MEMORY (60 * 1518)
+#define        RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
+                       (RX_MAX_QUEUE_MEMORY/(dev)->rx_urb_size) : 4)
+#define        TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? \
+                       (RX_MAX_QUEUE_MEMORY/(dev)->hard_mtu) : 4)
 
 // reawaken network queue this soon after stopping; else watchdog barks
 #define TX_TIMEOUT_JIFFIES     (5*HZ)
@@ -227,13 +230,23 @@ static int usbnet_change_mtu (struct net_device *net, int new_mtu)
 {
        struct usbnet   *dev = netdev_priv(net);
        int             ll_mtu = new_mtu + net->hard_header_len;
+       int             old_hard_mtu = dev->hard_mtu;
+       int             old_rx_urb_size = dev->rx_urb_size;
 
-       if (new_mtu <= 0 || ll_mtu > dev->hard_mtu)
+       if (new_mtu <= 0)
                return -EINVAL;
        // no second zero-length packet read wanted after mtu-sized packets
        if ((ll_mtu % dev->maxpacket) == 0)
                return -EDOM;
        net->mtu = new_mtu;
+
+       dev->hard_mtu = net->mtu + net->hard_header_len;
+       if (dev->rx_urb_size == old_hard_mtu) {
+               dev->rx_urb_size = dev->hard_mtu;
+               if (dev->rx_urb_size > old_rx_urb_size)
+                       usbnet_unlink_rx_urbs(dev);
+       }
+
        return 0;
 }
 
@@ -412,9 +425,9 @@ static void rx_complete (struct urb *urb, struct pt_regs *regs)
            // we get controller i/o faults during khubd disconnect() delays.
            // throttle down resubmits, to avoid log floods; just temporarily,
            // so we still recover when the fault isn't a khubd delay.
-           case -EPROTO:               // ehci
-           case -ETIMEDOUT:            // ohci
-           case -EILSEQ:               // uhci
+           case -EPROTO:
+           case -ETIME:
+           case -EILSEQ:
                dev->stats.rx_errors++;
                if (!timer_pending (&dev->delay)) {
                        mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES);
@@ -521,6 +534,17 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
        return count;
 }
 
+// Flush all pending rx urbs
+// minidrivers may need to do this when the MTU changes
+
+void usbnet_unlink_rx_urbs(struct usbnet *dev)
+{
+       if (netif_running(dev->net)) {
+               (void) unlink_urbs (dev, &dev->rxq);
+               tasklet_schedule(&dev->bh);
+       }
+}
+EXPORT_SYMBOL_GPL(usbnet_unlink_rx_urbs);
 
 /*-------------------------------------------------------------------------*/
 
@@ -629,7 +653,7 @@ static int usbnet_open (struct net_device *net)
 
                devinfo (dev, "open: enable queueing "
                                "(rx %d, tx %d) mtu %d %s framing",
-                       RX_QLEN (dev), TX_QLEN (dev), dev->net->mtu,
+                       (int)RX_QLEN (dev), (int)TX_QLEN (dev), dev->net->mtu,
                        framing);
        }
 
@@ -797,9 +821,9 @@ static void tx_complete (struct urb *urb, struct pt_regs *regs)
 
                // like rx, tx gets controller i/o faults during khubd delays
                // and so it uses the same throttling mechanism.
-               case -EPROTO:           // ehci
-               case -ETIMEDOUT:        // ohci
-               case -EILSEQ:           // uhci
+               case -EPROTO:
+               case -ETIME:
+               case -EILSEQ:
                        if (!timer_pending (&dev->delay)) {
                                mod_timer (&dev->delay,
                                        jiffies + THROTTLE_JIFFIES);
index 89fc4958eecf81f72c5f93128d5994168b7f3c43..c0746f0454afe277e4d970e81f6f36ea48305b25 100644 (file)
@@ -166,6 +166,7 @@ struct skb_data {   /* skb->cb is one of these */
 extern int usbnet_get_endpoints(struct usbnet *, struct usb_interface *);
 extern void usbnet_defer_kevent (struct usbnet *, int);
 extern void usbnet_skb_return (struct usbnet *, struct sk_buff *);
+extern void usbnet_unlink_rx_urbs(struct usbnet *);
 
 extern u32 usbnet_get_msglevel (struct net_device *);
 extern void usbnet_set_msglevel (struct net_device *, u32);
index f5b9438c94f0f29bd35392906b59759420ebad44..5076b9d97057aee810faf064414485eec2f475e9 100644 (file)
@@ -53,6 +53,15 @@ config USB_SERIAL_GENERIC
          support" be compiled as a module for this driver to be used
          properly.
 
+config USB_SERIAL_AIRCABLE
+       tristate "AIRcable USB Bluetooth Dongle Driver (EXPERIMENTAL)"
+       depends on USB_SERIAL && EXPERIMENTAL
+       help
+           Say Y here if you want to use AIRcable USB Bluetoot Dongle.
+
+           To compile this driver as a module, choose M here: the module
+           will be called aircable.
+
 config USB_SERIAL_AIRPRIME
        tristate "USB AirPrime CDMA Wireless Driver"
        depends on USB_SERIAL
@@ -413,6 +422,21 @@ config USB_SERIAL_MCT_U232
          To compile this driver as a module, choose M here: the
          module will be called mct_u232.
 
+config USB_SERIAL_MOS7840
+       tristate "USB Moschip 7840/7820 USB Serial Driver"
+       depends on USB_SERIAL
+       ---help---
+         Say Y here if you want to use a MCS7840 Quad-Serial or MCS7820
+         Dual-Serial port device from MosChip Semiconductor.
+
+         The MCS7840 and MCS7820 have been developed to connect a wide range
+         of standard serial devices to a USB host.  The MCS7840 has a USB
+         device controller connected to four (4) individual UARTs while the
+         MCS7820 controller connects to two (2) individual UARTs.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mos7840.  If unsure, choose N.
+
 config USB_SERIAL_NAVMAN
        tristate "USB Navman GPS device"
        depends on USB_SERIAL
@@ -526,5 +550,6 @@ config USB_EZUSB
        depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
        default y
 
+
 endmenu
 
index 8efed2ce1ba38260f97968b4c9c9e84f86fbf491..8dce83340e3109aa655d84512524f82510fe48cf 100644 (file)
@@ -11,6 +11,7 @@ usbserial-obj-$(CONFIG_USB_EZUSB)             += ezusb.o
 
 usbserial-objs := usb-serial.o generic.o bus.o $(usbserial-obj-y)
 
+obj-$(CONFIG_USB_SERIAL_AIRCABLE)              += aircable.o
 obj-$(CONFIG_USB_SERIAL_AIRPRIME)              += airprime.o
 obj-$(CONFIG_USB_SERIAL_ARK3116)               += ark3116.o
 obj-$(CONFIG_USB_SERIAL_BELKIN)                        += belkin_sa.o
@@ -33,6 +34,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA)          += keyspan_pda.o
 obj-$(CONFIG_USB_SERIAL_KLSI)                  += kl5kusb105.o
 obj-$(CONFIG_USB_SERIAL_KOBIL_SCT)             += kobil_sct.o
 obj-$(CONFIG_USB_SERIAL_MCT_U232)              += mct_u232.o
+obj-$(CONFIG_USB_SERIAL_MOS7840)               += mos7840.o
 obj-$(CONFIG_USB_SERIAL_NAVMAN)                        += navman.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)               += omninet.o
 obj-$(CONFIG_USB_SERIAL_OPTION)                        += option.o
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c
new file mode 100644 (file)
index 0000000..2ccd9de
--- /dev/null
@@ -0,0 +1,625 @@
+/*
+ * AIRcable USB Bluetooth Dongle Driver.
+ *
+ * Copyright (C) 2006 Manuel Francisco Naranjo (naranjo.manuel@gmail.com)
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * The device works as an standard CDC device, it has 2 interfaces, the first
+ * one is for firmware access and the second is the serial one.
+ * The protocol is very simply, there are two posibilities reading or writing.
+ * When writting the first urb must have a Header that starts with 0x20 0x29 the
+ * next two bytes must say how much data will be sended.
+ * When reading the process is almost equal except that the header starts with
+ * 0x00 0x20.
+ *
+ * The device simply need some stuff to understand data comming from the usb
+ * buffer: The First and Second byte is used for a Header, the Third and Fourth
+ * tells the  device the amount of information the package holds.
+ * Packages are 60 bytes long Header Stuff.
+ * When writting to the device the first two bytes of the header are 0x20 0x29
+ * When reading the bytes are 0x00 0x20, or 0x00 0x10, there is an strange
+ * situation, when too much data arrives to the device because it sends the data
+ * but with out the header. I will use a simply hack to override this situation,
+ * if there is data coming that does not contain any header, then that is data
+ * that must go directly to the tty, as there is no documentation about if there
+ * is any other control code, I will simply check for the first
+ * one.
+ *
+ * The driver registers himself with the USB-serial core and the USB Core. I had
+ * to implement a probe function agains USB-serial, because other way, the
+ * driver was attaching himself to both interfaces. I have tryed with different
+ * configurations of usb_serial_driver with out exit, only the probe function
+ * could handle this correctly.
+ *
+ * I have taken some info from a Greg Kroah-Hartman article:
+ * http://www.linuxjournal.com/article/6573
+ * And from Linux Device Driver Kit CD, which is a great work, the authors taken
+ * the work to recompile lots of information an knowladge in drivers development
+ * and made it all avaible inside a cd.
+ * URL: http://kernel.org/pub/linux/kernel/people/gregkh/ddk/
+ *
+ */
+
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/circ_buf.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+
+static int debug;
+
+/* Vendor and Product ID */
+#define AIRCABLE_VID           0x16CA
+#define AIRCABLE_USB_PID       0x1502
+
+/* write buffer size defines */
+#define AIRCABLE_BUF_SIZE      2048
+
+/* Protocol Stuff */
+#define HCI_HEADER_LENGTH      0x4
+#define TX_HEADER_0            0x20
+#define TX_HEADER_1            0x29
+#define RX_HEADER_0            0x00
+#define RX_HEADER_1            0x20
+#define MAX_HCI_FRAMESIZE      60
+#define HCI_COMPLETE_FRAME     64
+
+/* rx_flags */
+#define THROTTLED              0x01
+#define ACTUALLY_THROTTLED     0x02
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v1.0b2"
+#define DRIVER_AUTHOR "Naranjo, Manuel Francisco <naranjo.manuel@gmail.com>"
+#define DRIVER_DESC "AIRcable USB Driver"
+
+/* ID table that will be registered with USB core */
+static struct usb_device_id id_table [] = {
+       { USB_DEVICE(AIRCABLE_VID, AIRCABLE_USB_PID) },
+       { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+
+/* Internal Structure */
+struct aircable_private {
+       spinlock_t rx_lock;             /* spinlock for the receive lines */
+       struct circ_buf *tx_buf;        /* write buffer */
+       struct circ_buf *rx_buf;        /* read buffer */
+       int rx_flags;                   /* for throttilng */
+       struct work_struct rx_work;     /* work cue for the receiving line */
+};
+
+/* Private methods */
+
+/* Circular Buffer Methods, code from ti_usb_3410_5052 used */
+/*
+ * serial_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void serial_buf_clear(struct circ_buf *cb)
+{
+       cb->head = cb->tail = 0;
+}
+
+/*
+ * serial_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static struct circ_buf *serial_buf_alloc(void)
+{
+       struct circ_buf *cb;
+       cb = kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
+       if (cb == NULL)
+               return NULL;
+       cb->buf = kmalloc(AIRCABLE_BUF_SIZE, GFP_KERNEL);
+       if (cb->buf == NULL) {
+               kfree(cb);
+               return NULL;
+       }
+       serial_buf_clear(cb);
+       return cb;
+}
+
+/*
+ * serial_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void serial_buf_free(struct circ_buf *cb)
+{
+       kfree(cb->buf);
+       kfree(cb);
+}
+
+/*
+ * serial_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+static int serial_buf_data_avail(struct circ_buf *cb)
+{
+       return CIRC_CNT(cb->head,cb->tail,AIRCABLE_BUF_SIZE);
+}
+
+/*
+ * serial_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+static int serial_buf_put(struct circ_buf *cb, const char *buf, int count)
+{
+       int c, ret = 0;
+       while (1) {
+               c = CIRC_SPACE_TO_END(cb->head, cb->tail, AIRCABLE_BUF_SIZE);
+               if (count < c)
+                       c = count;
+               if (c <= 0)
+                       break;
+               memcpy(cb->buf + cb->head, buf, c);
+               cb->head = (cb->head + c) & (AIRCABLE_BUF_SIZE-1);
+               buf += c;
+               count -= c;
+               ret= c;
+       }
+       return ret;
+}
+
+/*
+ * serial_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+static int serial_buf_get(struct circ_buf *cb, char *buf, int count)
+{
+       int c, ret = 0;
+       while (1) {
+               c = CIRC_CNT_TO_END(cb->head, cb->tail, AIRCABLE_BUF_SIZE);
+               if (count < c)
+                       c = count;
+               if (c <= 0)
+                       break;
+               memcpy(buf, cb->buf + cb->tail, c);
+               cb->tail = (cb->tail + c) & (AIRCABLE_BUF_SIZE-1);
+               buf += c;
+               count -= c;
+               ret= c;
+       }
+       return ret;
+}
+
+/* End of circula buffer methods */
+
+static void aircable_send(struct usb_serial_port *port)
+{
+       int count, result;
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       unsigned char* buf;
+       dbg("%s - port %d", __FUNCTION__, port->number);
+       if (port->write_urb_busy)
+               return;
+
+       count = min(serial_buf_data_avail(priv->tx_buf), MAX_HCI_FRAMESIZE);
+       if (count == 0)
+               return;
+
+       buf = kzalloc(count + HCI_HEADER_LENGTH, GFP_ATOMIC);
+       if (!buf) {
+               err("%s- kzalloc(%d) failed.", __FUNCTION__,
+                   count + HCI_HEADER_LENGTH);
+               return;
+       }
+
+       buf[0] = TX_HEADER_0;
+       buf[1] = TX_HEADER_1;
+       buf[2] = (unsigned char)count;
+       buf[3] = (unsigned char)(count >> 8);
+       serial_buf_get(priv->tx_buf,buf + HCI_HEADER_LENGTH, MAX_HCI_FRAMESIZE);
+
+       memcpy(port->write_urb->transfer_buffer, buf,
+              count + HCI_HEADER_LENGTH);
+
+       kfree(buf);
+       port->write_urb_busy = 1;
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+                             count + HCI_HEADER_LENGTH,
+                             port->write_urb->transfer_buffer);
+       port->write_urb->transfer_buffer_length = count + HCI_HEADER_LENGTH;
+       port->write_urb->dev = port->serial->dev;
+       result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+
+       if (result) {
+               dev_err(&port->dev,
+                       "%s - failed submitting write urb, error %d\n",
+                       __FUNCTION__, result);
+               port->write_urb_busy = 0;
+       }
+
+       schedule_work(&port->work);
+}
+
+static void aircable_read(void *params)
+{
+       struct usb_serial_port *port = params;
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       struct tty_struct *tty;
+       unsigned char *data;
+       int count;
+       if (priv->rx_flags & THROTTLED){
+               if (priv->rx_flags & ACTUALLY_THROTTLED)
+                       schedule_work(&priv->rx_work);
+               return;
+       }
+
+       /* By now I will flush data to the tty in packages of no more than
+        * 64 bytes, to ensure I do not get throttled.
+        * Ask USB mailing list for better aproach.
+        */
+       tty = port->tty;
+
+       if (!tty)
+               schedule_work(&priv->rx_work);
+
+       count = min(64, serial_buf_data_avail(priv->rx_buf));
+
+       if (count <= 0)
+               return; //We have finished sending everything.
+
+       tty_prepare_flip_string(tty, &data, count);
+       if (!data){
+               err("%s- kzalloc(%d) failed.", __FUNCTION__, count);
+               return;
+       }
+
+       serial_buf_get(priv->rx_buf, data, count);
+
+       tty_flip_buffer_push(tty);
+
+       if (serial_buf_data_avail(priv->rx_buf))
+               schedule_work(&priv->rx_work);
+
+       return;
+}
+/* End of private methods */
+
+static int aircable_probe(struct usb_serial *serial,
+                         const struct usb_device_id *id)
+{
+       struct usb_host_interface *iface_desc = serial->interface->cur_altsetting;
+       struct usb_endpoint_descriptor *endpoint;
+       int num_bulk_out=0;
+       int i;
+
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+               endpoint = &iface_desc->endpoint[i].desc;
+               if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+                       ((endpoint->bmAttributes & 3) == 0x02)) {
+                       /* we found our bulk out endpoint */
+                       dbg("found bulk out on endpoint %d", i);
+                       ++num_bulk_out;
+               }
+       }
+
+       if (num_bulk_out == 0) {
+               dbg("Invalid interface, discarding");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int aircable_attach (struct usb_serial *serial)
+{
+       struct usb_serial_port *port = serial->port[0];
+       struct aircable_private *priv;
+
+       priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL);
+       if (!priv){
+               err("%s- kmalloc(%Zd) failed.", __FUNCTION__,
+                       sizeof(struct aircable_private));
+               return -ENOMEM;
+       }
+
+       /* Allocation of Circular Buffers */
+       priv->tx_buf = serial_buf_alloc();
+       if (priv->tx_buf == NULL) {
+               kfree(priv);
+               return -ENOMEM;
+       }
+
+       priv->rx_buf = serial_buf_alloc();
+       if (priv->rx_buf == NULL) {
+               kfree(priv->tx_buf);
+               kfree(priv);
+               return -ENOMEM;
+       }
+
+       priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
+       INIT_WORK(&priv->rx_work, aircable_read, port);
+
+       usb_set_serial_port_data(serial->port[0], priv);
+
+       return 0;
+}
+
+static void aircable_shutdown(struct usb_serial *serial)
+{
+
+       struct usb_serial_port *port = serial->port[0];
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+
+       dbg("%s", __FUNCTION__);
+
+       if (priv) {
+               serial_buf_free(priv->tx_buf);
+               serial_buf_free(priv->rx_buf);
+               usb_set_serial_port_data(port, NULL);
+               kfree(priv);
+       }
+}
+
+static int aircable_write_room(struct usb_serial_port *port)
+{
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       return serial_buf_data_avail(priv->tx_buf);
+}
+
+static int aircable_write(struct usb_serial_port *port,
+                         const unsigned char *source, int count)
+{
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       int temp;
+
+       dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
+
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, source);
+
+       if (!count){
+               dbg("%s - write request of 0 bytes", __FUNCTION__);
+               return count;
+       }
+
+       temp = serial_buf_put(priv->tx_buf, source, count);
+
+       aircable_send(port);
+
+       if (count > AIRCABLE_BUF_SIZE)
+               count = AIRCABLE_BUF_SIZE;
+
+       return count;
+
+}
+
+static void aircable_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = urb->context;
+       int result;
+
+       dbg("%s - urb->status: %d", __FUNCTION__ , urb->status);
+
+       /* This has been taken from cypress_m8.c cypress_write_int_callback */
+       switch (urb->status) {
+               case 0:
+                       /* success */
+                       break;
+               case -ECONNRESET:
+               case -ENOENT:
+               case -ESHUTDOWN:
+                       /* this urb is terminated, clean up */
+                       dbg("%s - urb shutting down with status: %d",
+                           __FUNCTION__, urb->status);
+                       port->write_urb_busy = 0;
+                       return;
+               default:
+                       /* error in the urb, so we have to resubmit it */
+                       dbg("%s - Overflow in write", __FUNCTION__);
+                       dbg("%s - nonzero write bulk status received: %d",
+                           __FUNCTION__, urb->status);
+                       port->write_urb->transfer_buffer_length = 1;
+                       port->write_urb->dev = port->serial->dev;
+                       result = usb_submit_urb(port->write_urb, GFP_KERNEL);
+                       if (result)
+                               dev_err(&urb->dev->dev,
+                                       "%s - failed resubmitting write urb, error %d\n",
+                                       __FUNCTION__, result);
+                       else
+                               return;
+       }
+
+       port->write_urb_busy = 0;
+
+       aircable_send(port);
+}
+
+static void aircable_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = urb->context;
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       struct tty_struct *tty;
+       unsigned long no_packages, remaining, package_length, i;
+       int result, shift = 0;
+       unsigned char *temp;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       if (urb->status) {
+               dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+               if (!port->open_count) {
+                       dbg("%s - port is closed, exiting.", __FUNCTION__);
+                       return;
+               }
+               if (urb->status == -EPROTO) {
+                       dbg("%s - caught -EPROTO, resubmitting the urb",
+                           __FUNCTION__);
+                       usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+                                         usb_rcvbulkpipe(port->serial->dev,
+                                                         port->bulk_in_endpointAddress),
+                                         port->read_urb->transfer_buffer,
+                                         port->read_urb->transfer_buffer_length,
+                                         aircable_read_bulk_callback, port);
+
+                       result = usb_submit_urb(urb, GFP_ATOMIC);
+                       if (result)
+                               dev_err(&urb->dev->dev,
+                                       "%s - failed resubmitting read urb, error %d\n",
+                                       __FUNCTION__, result);
+                       return;
+               }
+               dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
+               return;
+       }
+
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+                               urb->actual_length,urb->transfer_buffer);
+
+       tty = port->tty;
+       if (tty && urb->actual_length) {
+               if (urb->actual_length <= 2) {
+                       /* This is an incomplete package */
+                       serial_buf_put(priv->rx_buf, urb->transfer_buffer,
+                                      urb->actual_length);
+               } else {
+                       temp = urb->transfer_buffer;
+                       if (temp[0] == RX_HEADER_0)
+                               shift = HCI_HEADER_LENGTH;
+
+                       remaining = urb->actual_length;
+                       no_packages = urb->actual_length / (HCI_COMPLETE_FRAME);
+
+                       if (urb->actual_length % HCI_COMPLETE_FRAME != 0)
+                               no_packages+=1;
+
+                       for (i = 0; i < no_packages ;i++) {
+                               if (remaining > (HCI_COMPLETE_FRAME))
+                                       package_length = HCI_COMPLETE_FRAME;
+                               else
+                                       package_length = remaining;
+                               remaining -= package_length;
+
+                               serial_buf_put(priv->rx_buf,
+                                       urb->transfer_buffer + shift +
+                                       (HCI_COMPLETE_FRAME) * (i),
+                                       package_length - shift);
+                       }
+               }
+               aircable_read(port);
+       }
+
+       /* Schedule the next read _if_ we are still open */
+       if (port->open_count) {
+               usb_fill_bulk_urb(port->read_urb, port->serial->dev,
+                                 usb_rcvbulkpipe(port->serial->dev,
+                                                 port->bulk_in_endpointAddress),
+                                 port->read_urb->transfer_buffer,
+                                 port->read_urb->transfer_buffer_length,
+                                 aircable_read_bulk_callback, port);
+
+               result = usb_submit_urb(urb, GFP_ATOMIC);
+               if (result)
+                       dev_err(&urb->dev->dev,
+                               "%s - failed resubmitting read urb, error %d\n",
+                               __FUNCTION__, result);
+       }
+
+       return;
+}
+
+/* Based on ftdi_sio.c throttle */
+static void aircable_throttle(struct usb_serial_port *port)
+{
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       spin_lock_irqsave(&priv->rx_lock, flags);
+       priv->rx_flags |= THROTTLED;
+       spin_unlock_irqrestore(&priv->rx_lock, flags);
+}
+
+/* Based on ftdi_sio.c unthrottle */
+static void aircable_unthrottle(struct usb_serial_port *port)
+{
+       struct aircable_private *priv = usb_get_serial_port_data(port);
+       int actually_throttled;
+       unsigned long flags;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       spin_lock_irqsave(&priv->rx_lock, flags);
+       actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED;
+       priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED);
+       spin_unlock_irqrestore(&priv->rx_lock, flags);
+
+       if (actually_throttled)
+               schedule_work(&priv->rx_work);
+}
+
+static struct usb_serial_driver aircable_device = {
+       .description =          "aircable",
+       .id_table =             id_table,
+       .num_ports =            1,
+       .attach =               aircable_attach,
+       .probe =                aircable_probe,
+       .shutdown =             aircable_shutdown,
+       .write =                aircable_write,
+       .write_room =           aircable_write_room,
+       .write_bulk_callback =  aircable_write_bulk_callback,
+       .read_bulk_callback =   aircable_read_bulk_callback,
+       .throttle =             aircable_throttle,
+       .unthrottle =           aircable_unthrottle,
+};
+
+static struct usb_driver aircable_driver = {
+       .name =         "aircable",
+       .probe =        usb_serial_probe,
+       .disconnect =   usb_serial_disconnect,
+       .id_table =     id_table,
+};
+
+static int __init aircable_init (void)
+{
+       int retval;
+       retval = usb_serial_register(&aircable_device);
+       if (retval)
+               goto failed_serial_register;
+       retval = usb_register(&aircable_driver);
+       if (retval)
+               goto failed_usb_register;
+       return 0;
+
+failed_serial_register:
+       usb_serial_deregister(&aircable_device);
+failed_usb_register:
+       return retval;
+}
+
+static void __exit aircable_exit (void)
+{
+       usb_deregister(&aircable_driver);
+       usb_serial_deregister(&aircable_device);
+}
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+module_init(aircable_init);
+module_exit(aircable_exit);
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
index 62082532a8b346359899b2291c59a69a3b7bcfad..6e1a84a858d4df72eb6cf99ff4397d12aa23f9a2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * AirPrime CDMA Wireless Serial USB driver
  *
- * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>
+ * Copyright (C) 2005-2006 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 version
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/tty.h>
+#include <linux/tty_flip.h>
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
 static struct usb_device_id id_table [] = {
        { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
-       { USB_DEVICE(0xf3d, 0x0112) },  /* AirPrime CDMA Wireless PC Card */
-       { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
+       { USB_DEVICE(0x0f3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */
+       { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
+       { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
        { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */
        { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */
+       { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
+#define URB_TRANSFER_BUFFER_SIZE       4096
+#define NUM_READ_URBS                  4
+#define NUM_WRITE_URBS                 4
+#define NUM_BULK_EPS                   3
+#define MAX_BULK_EPS                   6
+
+/* if overridden by the user, then use their value for the size of the
+ * read and write urbs, and the number of endpoints */
+static int buffer_size = URB_TRANSFER_BUFFER_SIZE;
+static int endpoints = NUM_BULK_EPS;
+static int debug;
+struct airprime_private {
+       spinlock_t lock;
+       int outstanding_urbs;
+       int throttled;
+       struct urb *read_urbp[NUM_READ_URBS];
+};
+
+static void airprime_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = urb->context;
+       unsigned char *data = urb->transfer_buffer;
+       struct tty_struct *tty;
+       int result;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       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);
+
+       tty = port->tty;
+       if (tty && urb->actual_length) {
+               tty_insert_flip_string (tty, data, urb->actual_length);
+               tty_flip_buffer_push (tty);
+       }
+
+       result = usb_submit_urb (urb, GFP_ATOMIC);
+       if (result)
+               dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n",
+                       __FUNCTION__, result);
+       return;
+}
+
+static void airprime_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+       struct usb_serial_port *port = urb->context;
+       struct airprime_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* free up the transfer buffer, as usb_free_urb() does not do this */
+       kfree (urb->transfer_buffer);
+
+       if (urb->status)
+               dbg("%s - nonzero write bulk status received: %d",
+                   __FUNCTION__, urb->status);
+       spin_lock_irqsave(&priv->lock, flags);
+       --priv->outstanding_urbs;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       usb_serial_port_softint(port);
+}
+
+static int airprime_open(struct usb_serial_port *port, struct file *filp)
+{
+       struct airprime_private *priv = usb_get_serial_port_data(port);
+       struct usb_serial *serial = port->serial;
+       struct urb *urb;
+       char *buffer = NULL;
+       int i;
+       int result = 0;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* initialize our private data structure if it isn't already created */
+       if (!priv) {
+               priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+               if (!priv) {
+                       result = -ENOMEM;
+                       goto out;
+               }
+               spin_lock_init(&priv->lock);
+               usb_set_serial_port_data(port, priv);
+       }
+
+       for (i = 0; i < NUM_READ_URBS; ++i) {
+               buffer = kmalloc(buffer_size, GFP_KERNEL);
+               if (!buffer) {
+                       dev_err(&port->dev, "%s - out of memory.\n",
+                               __FUNCTION__);
+                       result = -ENOMEM;
+                       goto errout;
+               }
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!urb) {
+                       dev_err(&port->dev, "%s - no more urbs?\n",
+                               __FUNCTION__);
+                       result = -ENOMEM;
+                       goto errout;
+               }
+               usb_fill_bulk_urb(urb, serial->dev,
+                                 usb_rcvbulkpipe(serial->dev,
+                                                 port->bulk_out_endpointAddress),
+                                 buffer, buffer_size,
+                                 airprime_read_bulk_callback, port);
+               result = usb_submit_urb(urb, GFP_KERNEL);
+               if (result) {
+                       dev_err(&port->dev,
+                               "%s - failed submitting read urb %d for port %d, error %d\n",
+                               __FUNCTION__, i, port->number, result);
+                       goto errout;
+               }
+               /* remember this urb so we can kill it when the port is closed */
+               priv->read_urbp[i] = urb;
+       }
+       goto out;
+
+ errout:
+       /* some error happened, cancel any submitted urbs and clean up anything that
+          got allocated successfully */
+
+       for ( ; i >= 0; --i) {
+               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);
+               }
+       }
+
+ out:
+       return result;
+}
+
+static void airprime_close(struct usb_serial_port *port, struct file * filp)
+{
+       struct airprime_private *priv = usb_get_serial_port_data(port);
+       int i;
+
+       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]);
+               usb_free_urb (priv->read_urbp[i]);
+       }
+
+       /* free up private structure */
+       kfree (priv);
+       usb_set_serial_port_data(port, NULL);
+}
+
+static int airprime_write(struct usb_serial_port *port,
+                         const unsigned char *buf, int count)
+{
+       struct airprime_private *priv = usb_get_serial_port_data(port);
+       struct usb_serial *serial = port->serial;
+       struct urb *urb;
+       unsigned char *buffer;
+       unsigned long flags;
+       int status;
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (priv->outstanding_urbs > NUM_WRITE_URBS) {
+               spin_unlock_irqrestore(&priv->lock, flags);
+               dbg("%s - write limit hit\n", __FUNCTION__);
+               return 0;
+       }
+       spin_unlock_irqrestore(&priv->lock, flags);
+       buffer = kmalloc(count, GFP_ATOMIC);
+       if (!buffer) {
+               dev_err(&port->dev, "out of memory\n");
+               return -ENOMEM;
+       }
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               dev_err(&port->dev, "no more free urbs\n");
+               kfree (buffer);
+               return -ENOMEM;
+       }
+       memcpy (buffer, buf, count);
+
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+
+       usb_fill_bulk_urb(urb, serial->dev,
+                         usb_sndbulkpipe(serial->dev,
+                                         port->bulk_out_endpointAddress),
+                         buffer, count,
+                         airprime_write_bulk_callback, port);
+
+       /* send it down the pipe */
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+       if (status) {
+               dev_err(&port->dev,
+                       "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+                       __FUNCTION__, status);
+               count = status;
+               kfree (buffer);
+       } else {
+               spin_lock_irqsave(&priv->lock, flags);
+               ++priv->outstanding_urbs;
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+       /* we are done with this urb, so let the host driver
+        * really free it when it is finished with it */
+       usb_free_urb (urb);
+       return count;
+}
+
 static struct usb_driver airprime_driver = {
        .name =         "airprime",
        .probe =        usb_serial_probe,
        .disconnect =   usb_serial_disconnect,
        .id_table =     id_table,
-       .no_dynamic_id =        1,
+       .no_dynamic_id =        1,
 };
 
 static struct usb_serial_driver airprime_device = {
@@ -42,13 +280,17 @@ static struct usb_serial_driver airprime_device = {
        .num_interrupt_in =     NUM_DONT_CARE,
        .num_bulk_in =          NUM_DONT_CARE,
        .num_bulk_out =         NUM_DONT_CARE,
-       .num_ports =            1,
+       .open =                 airprime_open,
+       .close =                airprime_close,
+       .write =                airprime_write,
 };
 
 static int __init airprime_init(void)
 {
        int retval;
 
+       airprime_device.num_ports =
+               (endpoints > 0 && endpoints <= MAX_BULK_EPS) ? endpoints : NUM_BULK_EPS;
        retval = usb_serial_register(&airprime_device);
        if (retval)
                return retval;
@@ -60,6 +302,8 @@ static int __init airprime_init(void)
 
 static void __exit airprime_exit(void)
 {
+       dbg("%s", __FUNCTION__);
+
        usb_deregister(&airprime_driver);
        usb_serial_deregister(&airprime_device);
 }
@@ -67,3 +311,10 @@ static void __exit airprime_exit(void)
 module_init(airprime_init);
 module_exit(airprime_exit);
 MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled");
+module_param(buffer_size, int, 0);
+MODULE_PARM_DESC(buffer_size, "Size of the transfer buffers in bytes (default 4096)");
+module_param(endpoints, int, 0);
+MODULE_PARM_DESC(endpoints, "Number of bulk EPs to configure (default 3)");
index 970d9ef0a7a5cce77eadc5b9d09a5ec6c2cc798f..ca52f12f0e24847df78ccc44e84bcd47dff63e86 100644 (file)
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2006
+ *   Simon Schulz (ark3116_driver <at> auctionant.de)
+ *
  * ark3116
  * - implements a driver for the arkmicro ark3116 chipset (vendor=0x6547,
  *   productid=0x0232) (used in a datacable called KQ-U8A)
@@ -8,8 +11,6 @@
  *
  *  - based on logs created by usbsnoopy
  *
- *  Author   : Simon Schulz [ark3116_driver<AT>auctionant.de]
- *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
@@ -22,6 +23,8 @@
 #include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
+#include <linux/serial.h>
+#include <asm/uaccess.h>
 
 
 static int debug;
@@ -43,10 +46,10 @@ static inline void ARK3116_SND(struct usb_serial *serial, int seq,
 {
        int result;
        result = usb_control_msg(serial->dev,
-                                usb_sndctrlpipe(serial->dev,0),
+                                usb_sndctrlpipe(serial->dev, 0),
                                 request, requesttype, value, index,
-                                NULL,0x00, 1000);
-       dbg("%03d > ok",seq);
+                                NULL, 0x00, 1000);
+       dbg("%03d > ok", seq);
 }
 
 static inline void ARK3116_RCV(struct usb_serial *serial, int seq,
@@ -56,27 +59,25 @@ static inline void ARK3116_RCV(struct usb_serial *serial, int seq,
 {
        int result;
        result = usb_control_msg(serial->dev,
-                             usb_rcvctrlpipe(serial->dev,0),
-                             request, requesttype, value, index,
-                             buf, 0x0000001, 1000);
+                                usb_rcvctrlpipe(serial->dev, 0),
+                                request, requesttype, value, index,
+                                buf, 0x0000001, 1000);
        if (result)
-               dbg("%03d < %d bytes [0x%02X]",seq, result, buf[0]);
+               dbg("%03d < %d bytes [0x%02X]", seq, result, buf[0]);
        else
                dbg("%03d < 0 bytes", seq);
 }
 
-
 static inline void ARK3116_RCV_QUIET(struct usb_serial *serial,
                                     __u8 request, __u8 requesttype,
                                     __u16 value, __u16 index, char *buf)
 {
        usb_control_msg(serial->dev,
-                       usb_rcvctrlpipe(serial->dev,0),
+                       usb_rcvctrlpipe(serial->dev, 0),
                        request, requesttype, value, index,
                        buf, 0x0000001, 1000);
 }
 
-
 static int ark3116_attach(struct usb_serial *serial)
 {
        char *buf;
@@ -84,10 +85,10 @@ static int ark3116_attach(struct usb_serial *serial)
        int i;
 
        for (i = 0; i < serial->num_ports; ++i) {
-               priv = kmalloc (sizeof (struct ark3116_private), GFP_KERNEL);
+               priv = kmalloc(sizeof (struct ark3116_private), GFP_KERNEL);
                if (!priv)
                        goto cleanup;
-               memset (priv, 0x00, sizeof (struct ark3116_private));
+               memset(priv, 0x00, sizeof (struct ark3116_private));
                spin_lock_init(&priv->lock);
 
                usb_set_serial_port_data(serial->port[i], priv);
@@ -95,63 +96,62 @@ static int ark3116_attach(struct usb_serial *serial)
 
        buf = kmalloc(1, GFP_KERNEL);
        if (!buf) {
-               dbg("error kmalloc -> out of mem ?");
+               dbg("error kmalloc -> out of mem?");
                goto cleanup;
        }
 
        /* 3 */
-       ARK3116_SND(serial, 3,0xFE,0x40,0x0008,0x0002);
-       ARK3116_SND(serial, 4,0xFE,0x40,0x0008,0x0001);
-       ARK3116_SND(serial, 5,0xFE,0x40,0x0000,0x0008);
-       ARK3116_SND(serial, 6,0xFE,0x40,0x0000,0x000B);
+       ARK3116_SND(serial, 3, 0xFE, 0x40, 0x0008, 0x0002);
+       ARK3116_SND(serial, 4, 0xFE, 0x40, 0x0008, 0x0001);
+       ARK3116_SND(serial, 5, 0xFE, 0x40, 0x0000, 0x0008);
+       ARK3116_SND(serial, 6, 0xFE, 0x40, 0x0000, 0x000B);
 
        /* <-- seq7 */
-       ARK3116_RCV(serial, 7,0xFE,0xC0,0x0000,0x0003, 0x00, buf);
-       ARK3116_SND(serial, 8,0xFE,0x40,0x0080,0x0003);
-       ARK3116_SND(serial, 9,0xFE,0x40,0x001A,0x0000);
-       ARK3116_SND(serial,10,0xFE,0x40,0x0000,0x0001);
-       ARK3116_SND(serial,11,0xFE,0x40,0x0000,0x0003);
+       ARK3116_RCV(serial,  7, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf);
+       ARK3116_SND(serial,  8, 0xFE, 0x40, 0x0080, 0x0003);
+       ARK3116_SND(serial,  9, 0xFE, 0x40, 0x001A, 0x0000);
+       ARK3116_SND(serial, 10, 0xFE, 0x40, 0x0000, 0x0001);
+       ARK3116_SND(serial, 11, 0xFE, 0x40, 0x0000, 0x0003);
 
        /* <-- seq12 */
-       ARK3116_RCV(serial,12,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
-       ARK3116_SND(serial,13,0xFE,0x40,0x0000,0x0004);
+       ARK3116_RCV(serial, 12, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
+       ARK3116_SND(serial, 13, 0xFE, 0x40, 0x0000, 0x0004);
 
        /* 14 */
-       ARK3116_RCV(serial,14,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
-       ARK3116_SND(serial,15,0xFE,0x40,0x0000,0x0004);
+       ARK3116_RCV(serial, 14, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
+       ARK3116_SND(serial, 15, 0xFE, 0x40, 0x0000, 0x0004);
 
        /* 16 */
-       ARK3116_RCV(serial,16,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+       ARK3116_RCV(serial, 16, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
        /* --> seq17 */
-       ARK3116_SND(serial,17,0xFE,0x40,0x0001,0x0004);
+       ARK3116_SND(serial, 17, 0xFE, 0x40, 0x0001, 0x0004);
 
        /* <-- seq18 */
-       ARK3116_RCV(serial,18,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
+       ARK3116_RCV(serial, 18, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf);
 
        /* --> seq19 */
-       ARK3116_SND(serial,19,0xFE,0x40,0x0003,0x0004);
-
+       ARK3116_SND(serial, 19, 0xFE, 0x40, 0x0003, 0x0004);
 
        /* <-- seq20 */
-       /* seems like serial port status info (RTS, CTS,...) */
-       /* returns modem control line status ?! */
-       ARK3116_RCV(serial,20,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
-
-       /* set 9600 baud & do some init ?! */
-       ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
-       ARK3116_SND(serial,148,0xFE,0x40,0x0038,0x0000);
-       ARK3116_SND(serial,149,0xFE,0x40,0x0001,0x0001);
-       ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
-       ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
-       ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
-       ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
-       ARK3116_SND(serial,154,0xFE,0x40,0x0003,0x0003);
+       /* seems like serial port status info (RTS, CTS, ...) */
+       /* returns modem control line status?! */
+       ARK3116_RCV(serial, 20, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf);
+
+       /* set 9600 baud & do some init?! */
+       ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003);
+       ARK3116_SND(serial, 148, 0xFE, 0x40, 0x0038, 0x0000);
+       ARK3116_SND(serial, 149, 0xFE, 0x40, 0x0001, 0x0001);
+       ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003);
+       ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf);
+       ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003);
+       ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf);
+       ARK3116_SND(serial, 154, 0xFE, 0x40, 0x0003, 0x0003);
 
        kfree(buf);
-       return(0);
+       return 0;
 
 cleanup:
-       for (--i; i>=0; --i)
+       for (--i; i >= 0; --i)
                usb_set_serial_port_data(serial->port[i], NULL);
        return -ENOMEM;
 }
@@ -180,7 +180,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
        spin_lock_irqsave(&priv->lock, flags);
        if (!priv->termios_initialized) {
                *(port->tty->termios) = tty_std_termios;
-               port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+               port->tty->termios->c_cflag = B9600 | CS8
+                                             | CREAD | HUPCL | CLOCAL;
                priv->termios_initialized = 1;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -204,8 +205,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
        }
 
        /* set data bit count (8/7/6/5) */
-       if (cflag & CSIZE){
-               switch (cflag & CSIZE){
+       if (cflag & CSIZE) {
+               switch (cflag & CSIZE) {
                case CS5:
                        config |= 0x00;
                        dbg("setting CS5");
@@ -219,7 +220,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
                        dbg("setting CS7");
                        break;
                default:
-                       err ("CSIZE was set but not CS5-CS8, using CS8!");
+                       err("CSIZE was set but not CS5-CS8, using CS8!");
+                       /* fall through */
                case CS8:
                        config |= 0x03;
                        dbg("setting CS8");
@@ -227,8 +229,8 @@ static void ark3116_set_termios(struct usb_serial_port *port,
                }
        }
 
-       /* set parity (NONE,EVEN,ODD) */
-       if (cflag & PARENB){
+       /* set parity (NONE/EVEN/ODD) */
+       if (cflag & PARENB) {
                if (cflag & PARODD) {
                        config |= 0x08;
                        dbg("setting parity to ODD");
@@ -240,20 +242,19 @@ static void ark3116_set_termios(struct usb_serial_port *port,
                dbg("setting parity to NONE");
        }
 
-       /* SET STOPBIT (1/2) */
+       /* set stop bit (1/2) */
        if (cflag & CSTOPB) {
                config |= 0x04;
-               dbg ("setting 2 stop bits");
+               dbg("setting 2 stop bits");
        } else {
-               dbg ("setting 1 stop bit");
+               dbg("setting 1 stop bit");
        }
 
-
-       /* set baudrate: */
+       /* set baudrate */
        baud = 0;
-       switch (cflag & CBAUD){
+       switch (cflag & CBAUD) {
                case B0:
-                       err("can't set 0baud, using 9600 instead");
+                       err("can't set 0 baud, using 9600 instead");
                        break;
                case B75:       baud = 75;      break;
                case B150:      baud = 150;     break;
@@ -285,38 +286,40 @@ static void ark3116_set_termios(struct usb_serial_port *port,
         */
        if (baud == 460800)
                /* strange, for 460800 the formula is wrong
-                * (dont use round(), then 9600baud is wrong) */
+                * if using round() then 9600baud is wrong) */
                ark3116_baud = 7;
        else
                ark3116_baud = 3000000 / baud;
 
        /* ? */
-       ARK3116_RCV(serial,0,0xFE,0xC0,0x0000,0x0003, 0x03, buf);
+       ARK3116_RCV(serial, 0, 0xFE, 0xC0, 0x0000, 0x0003, 0x03, buf);
+
        /* offset = buf[0]; */
        /* offset = 0x03; */
-       /* dbg("using 0x%04X as target for 0x0003:",0x0080+offset); */
-
+       /* dbg("using 0x%04X as target for 0x0003:", 0x0080 + offset); */
 
        /* set baudrate */
-       dbg("setting baudrate to %d (->reg=%d)",baud,ark3116_baud);
-       ARK3116_SND(serial,147,0xFE,0x40,0x0083,0x0003);
-       ARK3116_SND(serial,148,0xFE,0x40,(ark3116_baud & 0x00FF)   ,0x0000);
-       ARK3116_SND(serial,149,0xFE,0x40,(ark3116_baud & 0xFF00)>>8,0x0001);
-       ARK3116_SND(serial,150,0xFE,0x40,0x0003,0x0003);
+       dbg("setting baudrate to %d (->reg=%d)", baud, ark3116_baud);
+       ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003);
+       ARK3116_SND(serial, 148, 0xFE, 0x40,
+                           (ark3116_baud & 0x00FF), 0x0000);
+       ARK3116_SND(serial, 149, 0xFE, 0x40,
+                           (ark3116_baud & 0xFF00) >> 8, 0x0001);
+       ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003);
 
        /* ? */
-       ARK3116_RCV(serial,151,0xFE,0xC0,0x0000,0x0004,0x03, buf);
-       ARK3116_SND(serial,152,0xFE,0x40,0x0000,0x0003);
+       ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf);
+       ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003);
 
        /* set data bit count, stop bit count & parity: */
        dbg("updating bit count, stop bit or parity (cfg=0x%02X)", config);
-       ARK3116_RCV(serial,153,0xFE,0xC0,0x0000,0x0003,0x00, buf);
-       ARK3116_SND(serial,154,0xFE,0x40,config,0x0003);
+       ARK3116_RCV(serial, 153, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf);
+       ARK3116_SND(serial, 154, 0xFE, 0x40, config, 0x0003);
 
        if (cflag & CRTSCTS)
-               dbg("CRTSCTS not supported by chipset ?!");
+               dbg("CRTSCTS not supported by chipset?!");
 
-       /* TEST ARK3116_SND(154,0xFE,0x40,0xFFFF, 0x0006); */
+       /* TEST ARK3116_SND(154, 0xFE, 0x40, 0xFFFF, 0x0006); */
 
        kfree(buf);
        return;
@@ -329,11 +332,11 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
        char *buf;
        int result = 0;
 
-       dbg("%s -  port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __FUNCTION__, port->number);
 
        buf = kmalloc(1, GFP_KERNEL);
        if (!buf) {
-               dbg("error kmalloc -> out of mem ?");
+               dbg("error kmalloc -> out of mem?");
                return -ENOMEM;
        }
 
@@ -342,44 +345,68 @@ static int ark3116_open(struct usb_serial_port *port, struct file *filp)
                return result;
 
        /* open */
-       ARK3116_RCV(serial,111,0xFE,0xC0,0x0000,0x0003, 0x02, buf);
+       ARK3116_RCV(serial, 111, 0xFE, 0xC0, 0x0000, 0x0003, 0x02, buf);
 
-       ARK3116_SND(serial,112,0xFE,0x40,0x0082,0x0003);
-       ARK3116_SND(serial,113,0xFE,0x40,0x001A,0x0000);
-       ARK3116_SND(serial,114,0xFE,0x40,0x0000,0x0001);
-       ARK3116_SND(serial,115,0xFE,0x40,0x0002,0x0003);
+       ARK3116_SND(serial, 112, 0xFE, 0x40, 0x0082, 0x0003);
+       ARK3116_SND(serial, 113, 0xFE, 0x40, 0x001A, 0x0000);
+       ARK3116_SND(serial, 114, 0xFE, 0x40, 0x0000, 0x0001);
+       ARK3116_SND(serial, 115, 0xFE, 0x40, 0x0002, 0x0003);
 
-       ARK3116_RCV(serial,116,0xFE,0xC0,0x0000,0x0004, 0x03, buf);
-       ARK3116_SND(serial,117,0xFE,0x40,0x0002,0x0004);
+       ARK3116_RCV(serial, 116, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf);
+       ARK3116_SND(serial, 117, 0xFE, 0x40, 0x0002, 0x0004);
 
-       ARK3116_RCV(serial,118,0xFE,0xC0,0x0000,0x0004, 0x02, buf);
-       ARK3116_SND(serial,119,0xFE,0x40,0x0000,0x0004);
+       ARK3116_RCV(serial, 118, 0xFE, 0xC0, 0x0000, 0x0004, 0x02, buf);
+       ARK3116_SND(serial, 119, 0xFE, 0x40, 0x0000, 0x0004);
 
-       ARK3116_RCV(serial,120,0xFE,0xC0,0x0000,0x0004, 0x00, buf);
+       ARK3116_RCV(serial, 120, 0xFE, 0xC0, 0x0000, 0x0004, 0x00, buf);
 
-       ARK3116_SND(serial,121,0xFE,0x40,0x0001,0x0004);
+       ARK3116_SND(serial, 121, 0xFE, 0x40, 0x0001, 0x0004);
 
-       ARK3116_RCV(serial,122,0xFE,0xC0,0x0000,0x0004, 0x01, buf);
+       ARK3116_RCV(serial, 122, 0xFE, 0xC0, 0x0000, 0x0004, 0x01, buf);
 
-       ARK3116_SND(serial,123,0xFE,0x40,0x0003,0x0004);
+       ARK3116_SND(serial, 123, 0xFE, 0x40, 0x0003, 0x0004);
 
-       /* returns different values (control lines ?!) */
-       ARK3116_RCV(serial,124,0xFE,0xC0,0x0000,0x0006, 0xFF, buf);
+       /* returns different values (control lines?!) */
+       ARK3116_RCV(serial, 124, 0xFE, 0xC0, 0x0000, 0x0006, 0xFF, buf);
 
-       /* initialise termios: */
+       /* initialise termios */
        if (port->tty)
                ark3116_set_termios(port, &tmp_termios);
 
        kfree(buf);
 
        return result;
-
 }
 
 static int ark3116_ioctl(struct usb_serial_port *port, struct file *file,
                         unsigned int cmd, unsigned long arg)
 {
-       dbg("ioctl not supported yet...");
+       struct serial_struct serstruct;
+       void __user *user_arg = (void __user *)arg;
+
+       switch (cmd) {
+       case TIOCGSERIAL:
+               /* XXX: Some of these values are probably wrong. */
+               memset(&serstruct, 0, sizeof (serstruct));
+               serstruct.type = PORT_16654;
+               serstruct.line = port->serial->minor;
+               serstruct.port = port->number;
+               serstruct.custom_divisor = 0;
+               serstruct.baud_base = 460800;
+
+               if (copy_to_user(user_arg, &serstruct, sizeof (serstruct)))
+                       return -EFAULT;
+
+               return 0;
+       case TIOCSSERIAL:
+               if (copy_from_user(&serstruct, user_arg, sizeof (serstruct)))
+                       return -EFAULT;
+               return 0;
+       default:
+               dbg("%s cmd 0x%04x not supported", __FUNCTION__, cmd);
+               break;
+       }
+
        return -ENOIOCTLCMD;
 }
 
@@ -389,7 +416,7 @@ static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file)
        char *buf;
        char temp;
 
-       /* seems like serial port status info (RTS, CTS,...) is stored
+       /* seems like serial port status info (RTS, CTS, ...) is stored
         * in reg(?) 0x0006
         * pcb connection point 11 = GND -> sets bit4 of response
         * pcb connection point  7 = GND -> sets bit6 of response
@@ -401,16 +428,16 @@ static int ark3116_tiocmget(struct usb_serial_port *port, struct file *file)
                return -ENOMEM;
        }
 
-       /* read register: */
-       ARK3116_RCV_QUIET(serial,0xFE,0xC0,0x0000,0x0006,buf);
+       /* read register */
+       ARK3116_RCV_QUIET(serial, 0xFE, 0xC0, 0x0000, 0x0006, buf);
        temp = buf[0];
        kfree(buf);
 
-       /* i do not really know if bit4=CTS and bit6=DSR... was just a
-        * quick guess !!
+       /* i do not really know if bit4=CTS and bit6=DSR... just a
+        * quick guess!
         */
-       return  (temp & (1<<4) ? TIOCM_CTS : 0) |
-               (temp & (1<<6) ? TIOCM_DSR : 0);
+       return (temp & (1<<4) ? TIOCM_CTS : 0)
+              | (temp & (1<<6) ? TIOCM_DSR : 0);
 }
 
 static struct usb_driver ark3116_driver = {
index ee70fddcab6031a8f1c045da4e71c09b3c4d1f9b..e1173c1aee37c1280931cf7e32b17589d833480d 100644 (file)
@@ -129,6 +129,9 @@ struct cypress_private {
        int cmd_ctrl;                      /* always set this to 1 before issuing a command */
        struct cypress_buf *buf;           /* write buffer */
        int write_urb_in_use;              /* write urb in use indicator */
+       int write_urb_interval;            /* interval to use for write urb */
+       int read_urb_interval;             /* interval to use for read urb */
+       int comm_is_ok;                    /* true if communication is (still) ok */
        int termios_initialized;
        __u8 line_control;                 /* holds dtr / rts value */
        __u8 current_status;               /* received from last read - info on dsr,cts,cd,ri,etc */
@@ -168,6 +171,7 @@ static int  cypress_tiocmset                (struct usb_serial_port *port, struct file *file,
 static int  cypress_chars_in_buffer    (struct usb_serial_port *port);
 static void cypress_throttle           (struct usb_serial_port *port);
 static void cypress_unthrottle         (struct usb_serial_port *port);
+static void cypress_set_dead           (struct usb_serial_port *port);
 static void cypress_read_int_callback  (struct urb *urb, struct pt_regs *regs);
 static void cypress_write_int_callback (struct urb *urb, struct pt_regs *regs);
 /* baud helper functions */
@@ -288,6 +292,9 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
        
        priv = usb_get_serial_port_data(port);
 
+       if (!priv->comm_is_ok)
+               return -ENODEV;
+
        switch(cypress_request_type) {
                case CYPRESS_SET_CONFIG:
 
@@ -365,13 +372,12 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
                                if (tries++ >= 3)
                                        break;
 
-                               if (retval == EPIPE)
-                                       usb_clear_halt(port->serial->dev, 0x00);
-                       } while (retval != 8 && retval != ENODEV);
+                       } while (retval != 8 && retval != -ENODEV);
 
-                       if (retval != 8)
+                       if (retval != 8) {
                                err("%s - failed sending serial line settings - %d", __FUNCTION__, retval);
-                       else {
+                               cypress_set_dead(port);
+                       } else {
                                spin_lock_irqsave(&priv->lock, flags);
                                priv->baud_rate = new_baudrate;
                                priv->cbr_mask = baud_mask;
@@ -392,12 +398,11 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
                                if (tries++ >= 3)
                                        break;
 
-                               if (retval == EPIPE)
-                                       usb_clear_halt(port->serial->dev, 0x00);
-                       } while (retval != 5 && retval != ENODEV);
+                       } while (retval != 5 && retval != -ENODEV);
 
                        if (retval != 5) {
                                err("%s - failed to retrieve serial line settings - %d", __FUNCTION__, retval);
+                               cypress_set_dead(port);
                                return retval;
                        } else {
                                spin_lock_irqsave(&priv->lock, flags);
@@ -419,6 +424,24 @@ static int cypress_serial_control (struct usb_serial_port *port, unsigned baud_m
 } /* cypress_serial_control */
 
 
+static void cypress_set_dead(struct usb_serial_port *port)
+{
+       struct cypress_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (!priv->comm_is_ok) {
+               spin_unlock_irqrestore(&priv->lock, flags);
+               return;
+       }
+       priv->comm_is_ok = 0;
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       err("cypress_m8 suspending failing port %d - interval might be too short",
+           port->number);
+}
+
+
 /* given a baud mask, it will return integer baud on success */
 static int mask_to_rate (unsigned mask)
 {
@@ -472,13 +495,15 @@ static unsigned rate_to_mask (int rate)
 static int generic_startup (struct usb_serial *serial)
 {
        struct cypress_private *priv;
+       struct usb_serial_port *port = serial->port[0];
 
-       dbg("%s - port %d", __FUNCTION__, serial->port[0]->number);
+       dbg("%s - port %d", __FUNCTION__, port->number);
 
        priv = kzalloc(sizeof (struct cypress_private), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
+       priv->comm_is_ok = !0;
        spin_lock_init(&priv->lock);
        priv->buf = cypress_buf_alloc(CYPRESS_BUF_SIZE);
        if (priv->buf == NULL) {
@@ -489,13 +514,24 @@ static int generic_startup (struct usb_serial *serial)
        
        usb_reset_configuration (serial->dev);
        
-       interval = 1;
        priv->cmd_ctrl = 0;
        priv->line_control = 0;
        priv->termios_initialized = 0;
        priv->rx_flags = 0;
        priv->cbr_mask = B300;
-       usb_set_serial_port_data(serial->port[0], priv);
+       if (interval > 0) {
+               priv->write_urb_interval = interval;
+               priv->read_urb_interval = interval;
+               dbg("%s - port %d read & write intervals forced to %d",
+                   __FUNCTION__,port->number,interval);
+       } else {
+               priv->write_urb_interval = port->interrupt_out_urb->interval;
+               priv->read_urb_interval = port->interrupt_in_urb->interval;
+               dbg("%s - port %d intervals: read=%d write=%d",
+                   __FUNCTION__,port->number,
+                   priv->read_urb_interval,priv->write_urb_interval);
+       }
+       usb_set_serial_port_data(port, priv);
        
        return 0;
 }
@@ -585,6 +621,9 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
+       if (!priv->comm_is_ok)
+               return -EIO;
+
        /* clear halts before open */
        usb_clear_halt(serial->dev, 0x81);
        usb_clear_halt(serial->dev, 0x02);
@@ -624,11 +663,12 @@ static int cypress_open (struct usb_serial_port *port, struct file *filp)
        usb_fill_int_urb(port->interrupt_in_urb, serial->dev,
                usb_rcvintpipe(serial->dev, port->interrupt_in_endpointAddress),
                port->interrupt_in_urb->transfer_buffer, port->interrupt_in_urb->transfer_buffer_length,
-               cypress_read_int_callback, port, interval);
+               cypress_read_int_callback, port, priv->read_urb_interval);
        result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
 
        if (result){
                dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
+               cypress_set_dead(port);
        }
 
        return result;
@@ -733,6 +773,9 @@ static void cypress_send(struct usb_serial_port *port)
        struct cypress_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        
+       if (!priv->comm_is_ok)
+               return;
+
        dbg("%s - port %d", __FUNCTION__, port->number);
        dbg("%s - interrupt out size is %d", __FUNCTION__, port->interrupt_out_size);
        
@@ -806,14 +849,16 @@ send:
        usb_serial_debug_data(debug, &port->dev, __FUNCTION__, port->interrupt_out_size,
                              port->interrupt_out_urb->transfer_buffer);
 
-       port->interrupt_out_urb->transfer_buffer_length = actual_size;
-       port->interrupt_out_urb->dev = port->serial->dev;
-       port->interrupt_out_urb->interval = interval;
+       usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev,
+               usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress),
+               port->interrupt_out_buffer, port->interrupt_out_size,
+               cypress_write_int_callback, port, priv->write_urb_interval);
        result = usb_submit_urb (port->interrupt_out_urb, GFP_ATOMIC);
        if (result) {
                dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__,
                        result);
                priv->write_urb_in_use = 0;
+               cypress_set_dead(port);
        }
 
        spin_lock_irqsave(&priv->lock, flags);
@@ -1214,13 +1259,18 @@ static void cypress_unthrottle (struct usb_serial_port *port)
        priv->rx_flags = 0;
        spin_unlock_irqrestore(&priv->lock, flags);
 
+       if (!priv->comm_is_ok)
+               return;
+
        if (actually_throttled) {
                port->interrupt_in_urb->dev = port->serial->dev;
 
                result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
-               if (result)
+               if (result) {
                        dev_err(&port->dev, "%s - failed submitting read urb, "
                                        "error %d\n", __FUNCTION__, result);
+                       cypress_set_dead(port);
+               }
        }
 }
 
@@ -1240,9 +1290,22 @@ static void cypress_read_int_callback(struct urb *urb, struct pt_regs *regs)
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (urb->status) {
-               dbg("%s - nonzero read status received: %d", __FUNCTION__,
-                               urb->status);
+       switch (urb->status) {
+       case 0: /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* precursor to disconnect so just go away */
+               return;
+       case -EPIPE:
+               usb_clear_halt(port->serial->dev,0x81);
+               break;
+       default:
+               /* something ugly is going on... */
+               dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n",
+                       __FUNCTION__,urb->status);
+               cypress_set_dead(port);
                return;
        }
 
@@ -1343,18 +1406,20 @@ continue_read:
 
        /* Continue trying to always read... unless the port has closed. */
 
-       if (port->open_count > 0) {
+       if (port->open_count > 0 && priv->comm_is_ok) {
                usb_fill_int_urb(port->interrupt_in_urb, port->serial->dev,
                                usb_rcvintpipe(port->serial->dev,
                                        port->interrupt_in_endpointAddress),
                                port->interrupt_in_urb->transfer_buffer,
                                port->interrupt_in_urb->transfer_buffer_length,
-                               cypress_read_int_callback, port, interval);
+                               cypress_read_int_callback, port, priv->read_urb_interval);
                result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
-               if (result)
+               if (result) {
                        dev_err(&urb->dev->dev, "%s - failed resubmitting "
                                        "read urb, error %d\n", __FUNCTION__,
                                        result);
+                       cypress_set_dead(port);
+               }
        }
 
        return;
@@ -1380,20 +1445,26 @@ static void cypress_write_int_callback(struct urb *urb, struct pt_regs *regs)
                        dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
                        priv->write_urb_in_use = 0;
                        return;
-               case -EPIPE: /* no break needed */
+               case -EPIPE: /* no break needed; clear halt and resubmit */
+                       if (!priv->comm_is_ok)
+                               break;
                        usb_clear_halt(port->serial->dev, 0x02);
-               default:
                        /* error in the urb, so we have to resubmit it */
-                       dbg("%s - Overflow in write", __FUNCTION__);
                        dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
                        port->interrupt_out_urb->transfer_buffer_length = 1;
                        port->interrupt_out_urb->dev = port->serial->dev;
                        result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC);
-                       if (result)
-                               dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
-                                       __FUNCTION__, result);
-                       else
+                       if (!result)
                                return;
+                       dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n",
+                               __FUNCTION__, result);
+                       cypress_set_dead(port);
+                       break;
+               default:
+                       dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n",
+                               __FUNCTION__,urb->status);
+                       cypress_set_dead(port);
+                       break;
        }
        
        priv->write_urb_in_use = 0;
index c6115aa1b4456ced571506c9f324e4a864e88aaf..1f7b72553f3729c01208553a370acc78cfbfdba4 100644 (file)
@@ -1101,25 +1101,29 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att
 static DEVICE_ATTR(latency_timer, S_IWUSR | S_IRUGO, show_latency_timer, store_latency_timer);
 static DEVICE_ATTR(event_char, S_IWUSR, NULL, store_event_char);
 
-static void create_sysfs_attrs(struct usb_serial *serial)
-{      
+static int create_sysfs_attrs(struct usb_serial *serial)
+{
        struct ftdi_private *priv;
        struct usb_device *udev;
+       int retval = 0;
 
        dbg("%s",__FUNCTION__);
-       
+
        priv = usb_get_serial_port_data(serial->port[0]);
        udev = serial->dev;
-       
+
        /* XXX I've no idea if the original SIO supports the event_char
         * sysfs parameter, so I'm playing it safe.  */
        if (priv->chip_type != SIO) {
                dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]);
-               device_create_file(&udev->dev, &dev_attr_event_char);
-               if (priv->chip_type == FT232BM || priv->chip_type == FT2232C) {
-                       device_create_file(&udev->dev, &dev_attr_latency_timer);
+               retval = device_create_file(&udev->dev, &dev_attr_event_char);
+               if ((!retval) &&
+                   (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) {
+                       retval = device_create_file(&udev->dev,
+                                                   &dev_attr_latency_timer);
                }
        }
+       return retval;
 }
 
 static void remove_sysfs_attrs(struct usb_serial *serial)
@@ -1162,7 +1166,8 @@ static int ftdi_sio_attach (struct usb_serial *serial)
        struct usb_serial_port *port = serial->port[0];
        struct ftdi_private *priv;
        struct ftdi_sio_quirk *quirk;
-       
+       int retval;
+
        dbg("%s",__FUNCTION__);
 
        priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
@@ -1203,15 +1208,18 @@ static int ftdi_sio_attach (struct usb_serial *serial)
        usb_set_serial_port_data(serial->port[0], priv);
 
        ftdi_determine_type (serial->port[0]);
-       create_sysfs_attrs(serial);
+       retval = create_sysfs_attrs(serial);
+       if (retval)
+               dev_err(&serial->dev->dev, "Error creating sysfs files, "
+                       "continuing\n");
 
        /* Check for device requiring special set up. */
        quirk = (struct ftdi_sio_quirk *)usb_get_serial_data(serial);
        if (quirk && quirk->setup) {
                quirk->setup(serial);
        }
-       
-       return (0);
+
+       return 0;
 } /* ftdi_sio_attach */
 
 
index 727852634be9c91526419fe243b6b009382d69fc..4b1196a8b09e946364fb28e8fdcb625900b78e9a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Garmin GPS driver
  *
- * Copyright (C) 2004 Hermann Kneissel herkne@users.sourceforge.net
+ * Copyright (C) 2006 Hermann Kneissel herkne@users.sourceforge.net
  *
  * The latest version of the driver can be found at
  * http://sourceforge.net/projects/garmin-gps/
@@ -37,6 +37,8 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
+#include <linux/version.h>
+
 /* the mode to be set when the port ist opened */
 static int initial_mode = 1;
 
@@ -50,7 +52,7 @@ static int debug = 0;
  */
 
 #define VERSION_MAJOR  0
-#define VERSION_MINOR  23
+#define VERSION_MINOR  28
 
 #define _STR(s) #s
 #define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
@@ -164,7 +166,8 @@ struct garmin_data {
 #define FLAGS_SESSION_REPLY1_SEEN 0x0080
 #define FLAGS_SESSION_REPLY2_SEEN 0x0040
 #define FLAGS_BULK_IN_ACTIVE      0x0020
-#define FLAGS_THROTTLED           0x0010
+#define FLAGS_BULK_IN_RESTART     0x0010
+#define FLAGS_THROTTLED           0x0008
 #define CLEAR_HALT_REQUIRED       0x0001
 
 #define FLAGS_QUEUING             0x0100
@@ -224,7 +227,7 @@ static struct usb_driver garmin_driver = {
        .probe =        usb_serial_probe,
        .disconnect =   usb_serial_disconnect,
        .id_table =     id_table,
-       .no_dynamic_id =        1,
+       .no_dynamic_id = 1,
 };
 
 
@@ -270,7 +273,7 @@ static inline int isAbortTrfCmnd(const unsigned char *buf)
 
 
 static void send_to_tty(struct usb_serial_port *port,
-                        char *data, unsigned int actual_length)
+                       char *data, unsigned int actual_length)
 {
        struct tty_struct *tty = port->tty;
 
@@ -294,15 +297,15 @@ static void send_to_tty(struct usb_serial_port *port,
  * queue a received (usb-)packet for later processing
  */
 static int pkt_add(struct garmin_data * garmin_data_p,
-                   unsigned char *data, unsigned int data_length)
+                  unsigned char *data, unsigned int data_length)
 {
+       int state = 0;
        int result = 0;
        unsigned long flags;
        struct garmin_packet *pkt;
 
        /* process only packets containg data ... */
        if (data_length) {
-               garmin_data_p->flags |= FLAGS_QUEUING;
                pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
                              GFP_ATOMIC);
                if (pkt == NULL) {
@@ -313,14 +316,16 @@ static int pkt_add(struct garmin_data * garmin_data_p,
                memcpy(pkt->data, data, data_length);
 
                spin_lock_irqsave(&garmin_data_p->lock, flags);
+               garmin_data_p->flags |= FLAGS_QUEUING;
                result = list_empty(&garmin_data_p->pktlist);
                pkt->seq = garmin_data_p->seq_counter++;
                list_add_tail(&pkt->list, &garmin_data_p->pktlist);
+               state = garmin_data_p->state;
                spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
                /* in serial mode, if someone is waiting for data from
                   the device, iconvert and send the next packet to tty. */
-               if (result && (garmin_data_p->state == STATE_GSP_WAIT_DATA)) {
+               if (result && (state == STATE_GSP_WAIT_DATA)) {
                        gsp_next_packet(garmin_data_p);
                }
        }
@@ -370,9 +375,9 @@ static void pkt_clear(struct garmin_data * garmin_data_p)
 static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
 {
        __u8 pkt[10];
-        __u8 cksum = 0;
-        __u8 *ptr = pkt;
-        unsigned  l = 0;
+       __u8 cksum = 0;
+       __u8 *ptr = pkt;
+       unsigned  l = 0;
 
        dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id);
 
@@ -416,7 +421,7 @@ static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
 static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
 {
        const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
-        __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
+       __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
 
        int cksum = 0;
        int n = 0;
@@ -447,11 +452,11 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
                n++;
        }
 
-       if ((0xff & (cksum + *recpkt)) != 0) {
-                dbg("%s - invalid checksum, expected %02x, got %02x",
-                        __FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
-                return -EINVPKT;
-        }
+       if ((0xff & (cksum + *recpkt)) != 0) {
+               dbg("%s - invalid checksum, expected %02x, got %02x",
+                       __FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
+               return -EINVPKT;
+       }
 
        usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL);
        usbdata[1] = __cpu_to_le32(pktid);
@@ -491,20 +496,28 @@ static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
  */
 
 static int gsp_receive(struct garmin_data * garmin_data_p,
-                       const unsigned char *buf, int count)
+                      const unsigned char *buf, int count)
 {
+       unsigned long flags;
        int offs = 0;
        int ack_or_nak_seen = 0;
        int i = 0;
-       __u8 *dest = garmin_data_p->inbuffer;
-       int size = garmin_data_p->insize;
+       __u8 *dest;
+       int size;
        // dleSeen: set if last byte read was a DLE
-       int dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN;
+       int dleSeen;
        // skip: if set, skip incoming data until possible start of
        //       new packet
-       int skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
+       int skip;
        __u8 data;
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
+       dest = garmin_data_p->inbuffer;
+       size = garmin_data_p->insize;
+       dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN;
+       skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+
        dbg("%s - dle=%d skip=%d size=%d count=%d",
                __FUNCTION__, dleSeen, skip, size, count);
 
@@ -572,6 +585,8 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
                }
        }
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
+
        garmin_data_p->insize = size;
 
        // copy flags back to structure
@@ -587,6 +602,11 @@ static int gsp_receive(struct garmin_data * garmin_data_p,
 
        if (ack_or_nak_seen) {
                garmin_data_p->state = STATE_GSP_WAIT_DATA;
+       }
+
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+
+       if (ack_or_nak_seen) {
                gsp_next_packet(garmin_data_p);
        }
 
@@ -676,7 +696,7 @@ static int gsp_send(struct garmin_data * garmin_data_p,
        src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
        if (k > (GARMIN_PKTHDR_LENGTH-2)) {
                /* can't add stuffing DLEs in place, move data to end 
-                   of buffer ... */
+                  of buffer ... */
                dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen;
                memcpy(dst, src, datalen);
                src = dst;
@@ -755,8 +775,9 @@ static void gsp_next_packet(struct garmin_data * garmin_data_p)
  * or even incomplete packets
  */
 static int nat_receive(struct garmin_data * garmin_data_p,
-                       const unsigned char *buf, int count)
+                      const unsigned char *buf, int count)
 {
+       unsigned long flags;
        __u8 * dest;
        int offs = 0;
        int result = count;
@@ -803,7 +824,9 @@ static int nat_receive(struct garmin_data * garmin_data_p,
                                /* if this was an abort-transfer command,
                                   flush all queued data. */
                                if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
+                                       spin_lock_irqsave(&garmin_data_p->lock, flags);
                                        garmin_data_p->flags |= FLAGS_DROP_DATA;
+                                       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                                        pkt_clear(garmin_data_p);
                                }
                        }
@@ -839,12 +862,15 @@ static void priv_status_resp(struct usb_serial_port *port)
 
 static int process_resetdev_request(struct usb_serial_port *port)
 {
+       unsigned long flags;
        int status;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED);
        garmin_data_p->state = STATE_RESET;
        garmin_data_p->serial_num = 0;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        usb_kill_urb (port->interrupt_in_urb);
        dbg("%s - usb_reset_device", __FUNCTION__ );
@@ -862,6 +888,7 @@ static int process_resetdev_request(struct usb_serial_port *port)
  */
 static int garmin_clear(struct garmin_data * garmin_data_p)
 {
+       unsigned long flags;
        int status = 0;
 
        struct usb_serial_port *port = garmin_data_p->port;
@@ -875,8 +902,10 @@ static int garmin_clear(struct garmin_data * garmin_data_p)
        /* flush all queued data */
        pkt_clear(garmin_data_p);
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->insize = 0;
        garmin_data_p->outsize = 0;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        return status;
 }
@@ -888,6 +917,7 @@ static int garmin_clear(struct garmin_data * garmin_data_p)
 
 static int garmin_init_session(struct usb_serial_port *port)
 {
+       unsigned long flags;
        struct usb_serial *serial = port->serial;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        int status = 0;
@@ -913,7 +943,9 @@ static int garmin_init_session(struct usb_serial_port *port)
 
                if (status >= 0) {
 
+                       spin_lock_irqsave(&garmin_data_p->lock, flags);
                        garmin_data_p->ignorePkts++;
+                       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
                        /* not needed, but the win32 driver does it too ... */
                        status = garmin_write_bulk(port,
@@ -921,7 +953,9 @@ static int garmin_init_session(struct usb_serial_port *port)
                                                   sizeof(GARMIN_START_SESSION_REQ2));
                        if (status >= 0) {
                                status = 0;
+                               spin_lock_irqsave(&garmin_data_p->lock, flags);
                                garmin_data_p->ignorePkts++;
+                               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                        }
                }
        }
@@ -935,6 +969,7 @@ static int garmin_init_session(struct usb_serial_port *port)
 
 static int garmin_open (struct usb_serial_port *port, struct file *filp)
 {
+       unsigned long flags;
        int status = 0;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
@@ -948,9 +983,11 @@ static int garmin_open (struct usb_serial_port *port, struct file *filp)
        if (port->tty)
                port->tty->low_latency = 1;
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->mode  = initial_mode;
        garmin_data_p->count = 0;
        garmin_data_p->flags = 0;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        /* shutdown any bulk reads that might be going on */
        usb_kill_urb (port->write_urb);
@@ -996,6 +1033,7 @@ static void garmin_close (struct usb_serial_port *port, struct file * filp)
 
 static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
 {
+       unsigned long flags;
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
@@ -1007,7 +1045,9 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
        if (urb->status) {
                dbg("%s - nonzero write bulk status received: %d",
                        __FUNCTION__, urb->status);
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
        }
 
        usb_serial_port_softint(port);
@@ -1015,8 +1055,9 @@ static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
 
 
 static int garmin_write_bulk (struct usb_serial_port *port,
-                              const unsigned char *buf, int count)
+                             const unsigned char *buf, int count)
 {
+       unsigned long flags;
        struct usb_serial *serial = port->serial;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        struct urb *urb;
@@ -1026,7 +1067,9 @@ static int garmin_write_bulk (struct usb_serial_port *port,
        dbg("%s - port %d, state %d", __FUNCTION__, port->number,
                garmin_data_p->state);
 
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->flags &= ~FLAGS_DROP_DATA;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        buffer = kmalloc (count, GFP_ATOMIC);
        if (!buffer) {
@@ -1053,7 +1096,9 @@ static int garmin_write_bulk (struct usb_serial_port *port,
        urb->transfer_flags |= URB_ZERO_PACKET;
 
        if (GARMIN_LAYERID_APPL == getLayerId(buffer)) {
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                if (garmin_data_p->mode == MODE_GARMIN_SERIAL)  {
                        pkt_clear(garmin_data_p);
                        garmin_data_p->state = STATE_GSP_WAIT_DATA;
@@ -1087,8 +1132,9 @@ static int garmin_write_bulk (struct usb_serial_port *port,
 
 
 static int garmin_write (struct usb_serial_port *port,
-                         const unsigned char *buf, int count)
+                        const unsigned char *buf, int count)
 {
+       unsigned long flags;
        int pktid, pktsiz, len;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        __le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
@@ -1139,7 +1185,9 @@ static int garmin_write (struct usb_serial_port *port,
                                break;
 
                        case PRIV_PKTID_RESET_REQ:
+                               spin_lock_irqsave(&garmin_data_p->lock, flags);
                                garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
+                               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                                break;
 
                        case PRIV_PKTID_SET_DEF_MODE:
@@ -1155,6 +1203,8 @@ static int garmin_write (struct usb_serial_port *port,
                }
        }
 
+       garmin_data_p->ignorePkts = 0;
+
        if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
                return gsp_receive(garmin_data_p, buf, count);
        } else {        /* MODE_NATIVE */
@@ -1177,10 +1227,10 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port)
 {
        /*
         * Report back the number of bytes currently in our input buffer.
-         * Will this lock up the driver - the buffer contains an incomplete
-         * package which will not be written to the device until it
-         * has been completed ?
-         */
+        * Will this lock up the driver - the buffer contains an incomplete
+        * package which will not be written to the device until it
+        * has been completed ?
+        */
        //struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
        //return garmin_data_p->insize;
        return 0;
@@ -1190,6 +1240,8 @@ static int garmin_chars_in_buffer (struct usb_serial_port *port)
 static void garmin_read_process(struct garmin_data * garmin_data_p,
                                 unsigned char *data, unsigned data_length)
 {
+       unsigned long flags;
+
        if (garmin_data_p->flags & FLAGS_DROP_DATA) {
                /* abort-transfer cmd is actice */
                dbg("%s - pkt dropped", __FUNCTION__);
@@ -1200,11 +1252,14 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
                   if a reset is required or not when closing
                   the device */
                if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
-                               sizeof(GARMIN_APP_LAYER_REPLY)))
+                               sizeof(GARMIN_APP_LAYER_REPLY))) {
+                       spin_lock_irqsave(&garmin_data_p->lock, flags);
                        garmin_data_p->flags |= FLAGS_APP_RESP_SEEN;
+                       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+               }
 
                /* if throttling is active or postprecessing is required
-                  put the received data in th input queue, otherwise
+                  put the received data in the input queue, otherwise
                   send it directly to the tty port */
                if (garmin_data_p->flags & FLAGS_QUEUING) {
                        pkt_add(garmin_data_p, data, data_length);
@@ -1221,6 +1276,7 @@ static void garmin_read_process(struct garmin_data * garmin_data_p,
 
 static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
 {
+       unsigned long flags;
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct usb_serial *serial =  port->serial;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
@@ -1245,19 +1301,30 @@ static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
 
        garmin_read_process(garmin_data_p, data, urb->actual_length);
 
-       /* Continue trying to read until nothing more is received  */
-       if (urb->actual_length > 0) {
-               usb_fill_bulk_urb (port->read_urb, serial->dev,
-                          usb_rcvbulkpipe (serial->dev,
-                                           port->bulk_in_endpointAddress),
-                          port->read_urb->transfer_buffer,
-                          port->read_urb->transfer_buffer_length,
-                          garmin_read_bulk_callback, port);
+       if (urb->actual_length == 0 &&
+                       0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) {
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
+               garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
                if (status)
                        dev_err(&port->dev,
                                "%s - failed resubmitting read urb, error %d\n",
                                __FUNCTION__, status);
+       } else if (urb->actual_length > 0) {
+               /* Continue trying to read until nothing more is received  */
+               if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) {
+                       status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+                       if (status)
+                               dev_err(&port->dev,
+                                       "%s - failed resubmitting read urb, error %d\n",
+                                       __FUNCTION__, status);
+               }
+       } else {
+               dbg("%s - end of bulk data", __FUNCTION__);
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
+               garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
        }
        return;
 }
@@ -1265,6 +1332,7 @@ static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
 
 static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
 {
+       unsigned long flags;
        int status;
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct usb_serial *serial = port->serial;
@@ -1297,25 +1365,41 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
 
                dbg("%s - bulk data available.", __FUNCTION__);
 
-               /* bulk data available */
-               usb_fill_bulk_urb (port->read_urb, serial->dev,
-                               usb_rcvbulkpipe (serial->dev,
-                               port->bulk_in_endpointAddress),
-                               port->read_urb->transfer_buffer,
-                               port->read_urb->transfer_buffer_length,
-                               garmin_read_bulk_callback, port);
-               status = usb_submit_urb(port->read_urb, GFP_KERNEL);
-               if (status) {
-                       dev_err(&port->dev,
-                               "%s - failed submitting read urb, error %d\n",
-                       __FUNCTION__, status);
+               if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
+
+                       /* bulk data available */
+                       usb_fill_bulk_urb (port->read_urb, serial->dev,
+                                       usb_rcvbulkpipe (serial->dev,
+                                       port->bulk_in_endpointAddress),
+                                       port->read_urb->transfer_buffer,
+                                       port->read_urb->transfer_buffer_length,
+                                       garmin_read_bulk_callback, port);
+                       status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+                       if (status) {
+                               dev_err(&port->dev,
+                                       "%s - failed submitting read urb, error %d\n",
+                               __FUNCTION__, status);
+                       } else {
+                               spin_lock_irqsave(&garmin_data_p->lock, flags);
+                               garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE;
+                               /* do not send this packet to the user */
+                               garmin_data_p->ignorePkts = 1;
+                               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+                       }
+               } else {
+                       /* bulk-in transfer still active */
+                       spin_lock_irqsave(&garmin_data_p->lock, flags);
+                       garmin_data_p->flags |= FLAGS_BULK_IN_RESTART;
+                       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                }
 
        } else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY))
                         && 0 == memcmp(data, GARMIN_START_SESSION_REPLY,
                                        sizeof(GARMIN_START_SESSION_REPLY))) {
 
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
                /* save the serial number */
                garmin_data_p->serial_num 
@@ -1330,7 +1414,9 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
                   ignore it. */
                dbg("%s - pkt ignored (%d)",
                        __FUNCTION__, garmin_data_p->ignorePkts);
+               spin_lock_irqsave(&garmin_data_p->lock, flags);
                garmin_data_p->ignorePkts--;
+               spin_unlock_irqrestore(&garmin_data_p->lock, flags);
        } else {
                garmin_read_process(garmin_data_p, data, urb->actual_length);
        }
@@ -1351,18 +1437,20 @@ static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
  */
 static int garmin_flush_queue(struct garmin_data * garmin_data_p)
 {
+       unsigned long flags;
        struct garmin_packet *pkt;
 
        if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) {
                pkt = pkt_pop(garmin_data_p);
                if (pkt != NULL) {
-
                        send_to_tty(garmin_data_p->port, pkt->data, pkt->size);
                        kfree(pkt);
                        mod_timer(&garmin_data_p->timer, (1)+jiffies);
 
                } else {
+                       spin_lock_irqsave(&garmin_data_p->lock, flags);
                        garmin_data_p->flags &= ~FLAGS_QUEUING;
+                       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
                }
        }
        return 0;
@@ -1371,26 +1459,41 @@ static int garmin_flush_queue(struct garmin_data * garmin_data_p)
 
 static void garmin_throttle (struct usb_serial_port *port)
 {
+       unsigned long flags;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
 
        dbg("%s - port %d", __FUNCTION__, port->number);
        /* set flag, data received will be put into a queue
           for later processing */
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 }
 
 
 static void garmin_unthrottle (struct usb_serial_port *port)
 {
+       unsigned long flags;
        struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+       int status;
 
        dbg("%s - port %d", __FUNCTION__, port->number);
+       spin_lock_irqsave(&garmin_data_p->lock, flags);
        garmin_data_p->flags &= ~FLAGS_THROTTLED;
+       spin_unlock_irqrestore(&garmin_data_p->lock, flags);
 
        /* in native mode send queued data to tty, in
           serial mode nothing needs to be done here */
        if (garmin_data_p->mode == MODE_NATIVE)
                garmin_flush_queue(garmin_data_p);
+
+       if (0 != (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) {
+               status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+               if (status)
+                       dev_err(&port->dev,
+                               "%s - failed resubmitting read urb, error %d\n",
+                               __FUNCTION__, status);
+       }
 }
 
 
@@ -1420,11 +1523,12 @@ static int garmin_attach (struct usb_serial *serial)
 
        dbg("%s", __FUNCTION__);
 
-       garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
+       garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL);
        if (garmin_data_p == NULL) {
                dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
                return -ENOMEM;
        }
+       memset (garmin_data_p, 0, sizeof(struct garmin_data));
        init_timer(&garmin_data_p->timer);
        spin_lock_init(&garmin_data_p->lock);
        INIT_LIST_HEAD(&garmin_data_p->pktlist);
@@ -1459,10 +1563,10 @@ static void garmin_shutdown (struct usb_serial *serial)
 /* All of the device info needed */
 static struct usb_serial_driver garmin_device = {
        .driver = {
-               .owner =        THIS_MODULE,
-               .name =         "garmin_gps",
+               .owner       = THIS_MODULE,
+               .name        = "garmin_gps",
        },
-       .description =          "Garmin GPS usb/tty",
+       .description         = "Garmin GPS usb/tty",
        .id_table            = id_table,
        .num_interrupt_in    = 1,
        .num_bulk_in         = 1,
@@ -1483,6 +1587,7 @@ static struct usb_serial_driver garmin_device = {
 };
 
 
+
 static int __init garmin_init (void)
 {
        int retval;
index 9840bade79f974acc9231665498500205ac0ff96..bfc6998cd16f41128b6f10c059952213a33b3c30 100644 (file)
@@ -652,11 +652,6 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
        port->bulk_out_size = port->write_urb->transfer_buffer_length = URBDATA_SIZE;
        
        msleep(1000*initial_wait);
-       /* Start reading from the device */
-       usb_fill_bulk_urb(port->read_urb, serial->dev, 
-                     usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-                     port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-                     ipaq_read_bulk_callback, port);
 
        /*
         * Send out control message observed in win98 sniffs. Not sure what
@@ -670,18 +665,31 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
                                0x1, 0, NULL, 0, 100);
-               if (result == 0) {
-                       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-                       if (result) {
-                               err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
-                               goto error;
-                       }
-                       return 0;
-               }
+               if (!result)
+                       break;
+
                msleep(1000);
        }
-       err("%s - failed doing control urb, error %d", __FUNCTION__, result);
-       goto error;
+
+       if (!retries && result) {
+               err("%s - failed doing control urb, error %d", __FUNCTION__,
+                   result);
+               goto error;
+       }
+
+       /* Start reading from the device */
+       usb_fill_bulk_urb(port->read_urb, serial->dev,
+                     usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+                     port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
+                     ipaq_read_bulk_callback, port);
+
+       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+       if (result) {
+               err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+               goto error;
+       }
+
+       return 0;
 
 enomem:
        result = -ENOMEM;
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
new file mode 100644 (file)
index 0000000..95bf571
--- /dev/null
@@ -0,0 +1,2962 @@
+/*
+ * 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
+ *
+ * Clean ups from Moschip version and a few ioctl implementations by:
+ *     Paul B Schroeder <pschroeder "at" uplogix "dot" com>
+ *
+ * Originally based on drivers/usb/serial/io_edgeport.c which is:
+ *      Copyright (C) 2000 Inside Out Networks, All rights reserved.
+ *      Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <asm/uaccess.h>
+
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "1.3.1"
+#define DRIVER_DESC "Moschip 7840/7820 USB Serial Driver"
+
+/*
+ * 16C50 UART register defines
+ */
+
+#define LCR_BITS_5             0x00    /* 5 bits/char */
+#define LCR_BITS_6             0x01    /* 6 bits/char */
+#define LCR_BITS_7             0x02    /* 7 bits/char */
+#define LCR_BITS_8             0x03    /* 8 bits/char */
+#define LCR_BITS_MASK          0x03    /* Mask for bits/char field */
+
+#define LCR_STOP_1             0x00    /* 1 stop bit */
+#define LCR_STOP_1_5           0x04    /* 1.5 stop bits (if 5   bits/char) */
+#define LCR_STOP_2             0x04    /* 2 stop bits   (if 6-8 bits/char) */
+#define LCR_STOP_MASK          0x04    /* Mask for stop bits field */
+
+#define LCR_PAR_NONE           0x00    /* No parity */
+#define LCR_PAR_ODD            0x08    /* Odd parity */
+#define LCR_PAR_EVEN           0x18    /* Even parity */
+#define LCR_PAR_MARK           0x28    /* Force parity bit to 1 */
+#define LCR_PAR_SPACE          0x38    /* Force parity bit to 0 */
+#define LCR_PAR_MASK           0x38    /* Mask for parity field */
+
+#define LCR_SET_BREAK          0x40    /* Set Break condition */
+#define LCR_DL_ENABLE          0x80    /* Enable access to divisor latch */
+
+#define MCR_DTR                0x01    /* Assert DTR */
+#define MCR_RTS                0x02    /* Assert RTS */
+#define MCR_OUT1               0x04    /* Loopback only: Sets state of RI */
+#define MCR_MASTER_IE          0x08    /* Enable interrupt outputs */
+#define MCR_LOOPBACK           0x10    /* Set internal (digital) loopback mode */
+#define MCR_XON_ANY            0x20    /* Enable any char to exit XOFF mode */
+
+#define MOS7840_MSR_CTS        0x10    /* Current state of CTS */
+#define MOS7840_MSR_DSR        0x20    /* Current state of DSR */
+#define MOS7840_MSR_RI         0x40    /* Current state of RI */
+#define MOS7840_MSR_CD         0x80    /* Current state of CD */
+
+/*
+ * Defines used for sending commands to port
+ */
+
+#define WAIT_FOR_EVER   (HZ * 0 )      /* timeout urb is wait for ever */
+#define MOS_WDR_TIMEOUT (HZ * 5 )      /* default urb timeout */
+
+#define MOS_PORT1       0x0200
+#define MOS_PORT2       0x0300
+#define MOS_VENREG      0x0000
+#define MOS_MAX_PORT   0x02
+#define MOS_WRITE       0x0E
+#define MOS_READ        0x0D
+
+/* Requests */
+#define MCS_RD_RTYPE    0xC0
+#define MCS_WR_RTYPE    0x40
+#define MCS_RDREQ       0x0D
+#define MCS_WRREQ       0x0E
+#define MCS_CTRL_TIMEOUT        500
+#define VENDOR_READ_LENGTH      (0x01)
+
+#define MAX_NAME_LEN    64
+
+#define ZLP_REG1  0x3A         //Zero_Flag_Reg1    58
+#define ZLP_REG5  0x3E         //Zero_Flag_Reg5    62
+
+/* For higher baud Rates use TIOCEXBAUD */
+#define TIOCEXBAUD     0x5462
+
+/* vendor id and device id defines */
+
+#define USB_VENDOR_ID_MOSCHIP           0x9710
+#define MOSCHIP_DEVICE_ID_7840          0x7840
+#define MOSCHIP_DEVICE_ID_7820          0x7820
+
+/* Interrupt Rotinue Defines    */
+
+#define SERIAL_IIR_RLS      0x06
+#define SERIAL_IIR_MS       0x00
+
+/*
+ *  Emulation of the bit mask on the LINE STATUS REGISTER.
+ */
+#define SERIAL_LSR_DR       0x0001
+#define SERIAL_LSR_OE       0x0002
+#define SERIAL_LSR_PE       0x0004
+#define SERIAL_LSR_FE       0x0008
+#define SERIAL_LSR_BI       0x0010
+
+#define MOS_MSR_DELTA_CTS   0x10
+#define MOS_MSR_DELTA_DSR   0x20
+#define MOS_MSR_DELTA_RI    0x40
+#define MOS_MSR_DELTA_CD    0x80
+
+// Serial Port register Address
+#define INTERRUPT_ENABLE_REGISTER  ((__u16)(0x01))
+#define FIFO_CONTROL_REGISTER      ((__u16)(0x02))
+#define LINE_CONTROL_REGISTER      ((__u16)(0x03))
+#define MODEM_CONTROL_REGISTER     ((__u16)(0x04))
+#define LINE_STATUS_REGISTER       ((__u16)(0x05))
+#define MODEM_STATUS_REGISTER      ((__u16)(0x06))
+#define SCRATCH_PAD_REGISTER       ((__u16)(0x07))
+#define DIVISOR_LATCH_LSB          ((__u16)(0x00))
+#define DIVISOR_LATCH_MSB          ((__u16)(0x01))
+
+#define CLK_MULTI_REGISTER         ((__u16)(0x02))
+#define CLK_START_VALUE_REGISTER   ((__u16)(0x03))
+
+#define SERIAL_LCR_DLAB            ((__u16)(0x0080))
+
+/*
+ * URB POOL related defines
+ */
+#define NUM_URBS                        16     /* URB Count */
+#define URB_TRANSFER_BUFFER_SIZE        32     /* URB Size  */
+
+
+static struct usb_device_id moschip_port_id_table[] = {
+       {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
+       {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
+       {}                      /* terminating entry */
+};
+
+static __devinitdata struct usb_device_id moschip_id_table_combined[] = {
+       {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)},
+       {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)},
+       {}                      /* terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, moschip_id_table_combined);
+
+/* This structure holds all of the local port information */
+
+struct moschip_port {
+       int port_num;           /*Actual port number in the device(1,2,etc) */
+       struct urb *write_urb;  /* write URB for this port */
+       struct urb *read_urb;   /* read URB for this port */
+       __u8 shadowLCR;         /* last LCR value received */
+       __u8 shadowMCR;         /* last MCR value received */
+       char open;
+       wait_queue_head_t wait_chase;   /* for handling sleeping while waiting for chase to finish */
+       wait_queue_head_t delta_msr_wait;       /* for handling sleeping while waiting for msr change to happen */
+       int delta_msr_cond;
+       struct async_icount icount;
+       struct usb_serial_port *port;   /* loop back to the owner of this object */
+
+       /*Offsets */
+       __u8 SpRegOffset;
+       __u8 ControlRegOffset;
+       __u8 DcrRegOffset;
+       //for processing control URBS in interrupt context
+       struct urb *control_urb;
+       char *ctrl_buf;
+       int MsrLsr;
+
+       struct urb *write_urb_pool[NUM_URBS];
+};
+
+
+static int debug;
+static int mos7840_num_ports;  //this says the number of ports in the device
+static int mos7840_num_open_ports;
+
+
+/*
+ * mos7840_set_reg_sync
+ *     To set the Control register by calling usb_fill_control_urb function
+ *     by passing usb_sndctrlpipe function as parameter.
+ */
+
+static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg,
+                               __u16 val)
+{
+       struct usb_device *dev = port->serial->dev;
+       val = val & 0x00ff;
+       dbg("mos7840_set_reg_sync offset is %x, value %x\n", reg, val);
+
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
+                              MCS_WR_RTYPE, val, reg, NULL, 0,
+                              MOS_WDR_TIMEOUT);
+}
+
+/*
+ * mos7840_get_reg_sync
+ *     To set the Uart register by calling usb_fill_control_urb function by
+ *     passing usb_rcvctrlpipe function as parameter.
+ */
+
+static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg,
+                               __u16 * val)
+{
+       struct usb_device *dev = port->serial->dev;
+       int ret = 0;
+
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
+                             MCS_RD_RTYPE, 0, reg, val, VENDOR_READ_LENGTH,
+                             MOS_WDR_TIMEOUT);
+       dbg("mos7840_get_reg_sync offset is %x, return val %x\n", reg, *val);
+       *val = (*val) & 0x00ff;
+       return ret;
+}
+
+/*
+ * mos7840_set_uart_reg
+ *     To set the Uart register by calling usb_fill_control_urb function by
+ *     passing usb_sndctrlpipe function as parameter.
+ */
+
+static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg,
+                               __u16 val)
+{
+
+       struct usb_device *dev = port->serial->dev;
+       val = val & 0x00ff;
+       // For the UART control registers, the application number need to be Or'ed
+       if (mos7840_num_ports == 4) {
+               val |=
+                   (((__u16) port->number - (__u16) (port->serial->minor)) +
+                    1) << 8;
+               dbg("mos7840_set_uart_reg application number is %x\n", val);
+       } else {
+               if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
+                       val |=
+                           (((__u16) port->number -
+                             (__u16) (port->serial->minor)) + 1) << 8;
+                       dbg("mos7840_set_uart_reg application number is %x\n",
+                           val);
+               } else {
+                       val |=
+                           (((__u16) port->number -
+                             (__u16) (port->serial->minor)) + 2) << 8;
+                       dbg("mos7840_set_uart_reg application number is %x\n",
+                           val);
+               }
+       }
+       return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ,
+                              MCS_WR_RTYPE, val, reg, NULL, 0,
+                              MOS_WDR_TIMEOUT);
+
+}
+
+/*
+ * mos7840_get_uart_reg
+ *     To set the Control register by calling usb_fill_control_urb function
+ *     by passing usb_rcvctrlpipe function as parameter.
+ */
+static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg,
+                               __u16 * val)
+{
+       struct usb_device *dev = port->serial->dev;
+       int ret = 0;
+       __u16 Wval;
+
+       //dbg("application number is %4x \n",(((__u16)port->number - (__u16)(port->serial->minor))+1)<<8);
+       /*Wval  is same as application number */
+       if (mos7840_num_ports == 4) {
+               Wval =
+                   (((__u16) port->number - (__u16) (port->serial->minor)) +
+                    1) << 8;
+               dbg("mos7840_get_uart_reg application number is %x\n", Wval);
+       } else {
+               if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) {
+                       Wval =
+                           (((__u16) port->number -
+                             (__u16) (port->serial->minor)) + 1) << 8;
+                       dbg("mos7840_get_uart_reg application number is %x\n",
+                           Wval);
+               } else {
+                       Wval =
+                           (((__u16) port->number -
+                             (__u16) (port->serial->minor)) + 2) << 8;
+                       dbg("mos7840_get_uart_reg application number is %x\n",
+                           Wval);
+               }
+       }
+       ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ,
+                             MCS_RD_RTYPE, Wval, reg, val, VENDOR_READ_LENGTH,
+                             MOS_WDR_TIMEOUT);
+       *val = (*val) & 0x00ff;
+       return ret;
+}
+
+static void mos7840_dump_serial_port(struct moschip_port *mos7840_port)
+{
+
+       dbg("***************************************\n");
+       dbg("SpRegOffset is %2x\n", mos7840_port->SpRegOffset);
+       dbg("ControlRegOffset is %2x \n", mos7840_port->ControlRegOffset);
+       dbg("DCRRegOffset is %2x \n", mos7840_port->DcrRegOffset);
+       dbg("***************************************\n");
+
+}
+
+/************************************************************************/
+/************************************************************************/
+/*             I N T E R F A C E   F U N C T I O N S                   */
+/*             I N T E R F A C E   F U N C T I O N S                   */
+/************************************************************************/
+/************************************************************************/
+
+static inline void mos7840_set_port_private(struct usb_serial_port *port,
+                                           struct moschip_port *data)
+{
+       usb_set_serial_port_data(port, (void *)data);
+}
+
+static inline struct moschip_port *mos7840_get_port_private(struct
+                                                           usb_serial_port
+                                                           *port)
+{
+       return (struct moschip_port *)usb_get_serial_port_data(port);
+}
+
+static int mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
+{
+       struct moschip_port *mos7840_port;
+       struct async_icount *icount;
+       mos7840_port = port;
+       icount = &mos7840_port->icount;
+       if (new_msr &
+           (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |
+            MOS_MSR_DELTA_CD)) {
+               icount = &mos7840_port->icount;
+
+               /* update input line counters */
+               if (new_msr & MOS_MSR_DELTA_CTS) {
+                       icount->cts++;
+               }
+               if (new_msr & MOS_MSR_DELTA_DSR) {
+                       icount->dsr++;
+               }
+               if (new_msr & MOS_MSR_DELTA_CD) {
+                       icount->dcd++;
+               }
+               if (new_msr & MOS_MSR_DELTA_RI) {
+                       icount->rng++;
+               }
+       }
+
+       return 0;
+}
+
+static int mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
+{
+       struct async_icount *icount;
+
+       dbg("%s - %02x", __FUNCTION__, new_lsr);
+
+       if (new_lsr & SERIAL_LSR_BI) {
+               //
+               // Parity and Framing errors only count if they
+               // occur exclusive of a break being
+               // received.
+               //
+               new_lsr &= (__u8) (SERIAL_LSR_OE | SERIAL_LSR_BI);
+       }
+
+       /* update input line counters */
+       icount = &port->icount;
+       if (new_lsr & SERIAL_LSR_BI) {
+               icount->brk++;
+       }
+       if (new_lsr & SERIAL_LSR_OE) {
+               icount->overrun++;
+       }
+       if (new_lsr & SERIAL_LSR_PE) {
+               icount->parity++;
+       }
+       if (new_lsr & SERIAL_LSR_FE) {
+               icount->frame++;
+       }
+
+       return 0;
+}
+
+/************************************************************************/
+/************************************************************************/
+/*            U S B  C A L L B A C K   F U N C T I O N S                */
+/*            U S B  C A L L B A C K   F U N C T I O N S                */
+/************************************************************************/
+/************************************************************************/
+
+static void mos7840_control_callback(struct urb *urb, struct pt_regs *regs)
+{
+       unsigned char *data;
+       struct moschip_port *mos7840_port;
+       __u8 regval = 0x0;
+
+       if (!urb) {
+               dbg("%s", "Invalid Pointer !!!!:\n");
+               return;
+       }
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+                   urb->status);
+               return;
+       default:
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+                   urb->status);
+               goto exit;
+       }
+
+       mos7840_port = (struct moschip_port *)urb->context;
+
+       dbg("%s urb buffer size is %d\n", __FUNCTION__, urb->actual_length);
+       dbg("%s mos7840_port->MsrLsr is %d port %d\n", __FUNCTION__,
+           mos7840_port->MsrLsr, mos7840_port->port_num);
+       data = urb->transfer_buffer;
+       regval = (__u8) data[0];
+       dbg("%s data is %x\n", __FUNCTION__, regval);
+       if (mos7840_port->MsrLsr == 0)
+               mos7840_handle_new_msr(mos7840_port, regval);
+       else if (mos7840_port->MsrLsr == 1)
+               mos7840_handle_new_lsr(mos7840_port, regval);
+
+      exit:
+       return;
+}
+
+static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
+                          __u16 * val)
+{
+       struct usb_device *dev = mcs->port->serial->dev;
+       struct usb_ctrlrequest *dr = NULL;
+       unsigned char *buffer = NULL;
+       int ret = 0;
+       buffer = (__u8 *) mcs->ctrl_buf;
+
+//      dr=(struct usb_ctrlrequest *)(buffer);
+       dr = (void *)(buffer + 2);
+       dr->bRequestType = MCS_RD_RTYPE;
+       dr->bRequest = MCS_RDREQ;
+       dr->wValue = cpu_to_le16(Wval); //0;
+       dr->wIndex = cpu_to_le16(reg);
+       dr->wLength = cpu_to_le16(2);
+
+       usb_fill_control_urb(mcs->control_urb, dev, usb_rcvctrlpipe(dev, 0),
+                            (unsigned char *)dr, buffer, 2,
+                            mos7840_control_callback, mcs);
+       mcs->control_urb->transfer_buffer_length = 2;
+       ret = usb_submit_urb(mcs->control_urb, GFP_ATOMIC);
+       return ret;
+}
+
+/*****************************************************************************
+ * mos7840_interrupt_callback
+ *     this is the callback function for when we have received data on the
+ *     interrupt endpoint.
+ *****************************************************************************/
+
+static void mos7840_interrupt_callback(struct urb *urb, struct pt_regs *regs)
+{
+       int result;
+       int length;
+       struct moschip_port *mos7840_port;
+       struct usb_serial *serial;
+       __u16 Data;
+       unsigned char *data;
+       __u8 sp[5], st;
+       int i;
+       __u16 wval;
+
+       dbg("%s", " : Entering\n");
+       if (!urb) {
+               dbg("%s", "Invalid Pointer !!!!:\n");
+               return;
+       }
+
+       switch (urb->status) {
+       case 0:
+               /* success */
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+                   urb->status);
+               return;
+       default:
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+                   urb->status);
+               goto exit;
+       }
+
+       length = urb->actual_length;
+       data = urb->transfer_buffer;
+
+       serial = (struct usb_serial *)urb->context;
+
+       /* Moschip get 5 bytes
+        * Byte 1 IIR Port 1 (port.number is 0)
+        * Byte 2 IIR Port 2 (port.number is 1)
+        * Byte 3 IIR Port 3 (port.number is 2)
+        * Byte 4 IIR Port 4 (port.number is 3)
+        * Byte 5 FIFO status for both */
+
+       if (length && length > 5) {
+               dbg("%s \n", "Wrong data !!!");
+               return;
+       }
+
+       sp[0] = (__u8) data[0];
+       sp[1] = (__u8) data[1];
+       sp[2] = (__u8) data[2];
+       sp[3] = (__u8) data[3];
+       st = (__u8) data[4];
+
+       for (i = 0; i < serial->num_ports; i++) {
+               mos7840_port = mos7840_get_port_private(serial->port[i]);
+               wval =
+                   (((__u16) serial->port[i]->number -
+                     (__u16) (serial->minor)) + 1) << 8;
+               if (mos7840_port->open) {
+                       if (sp[i] & 0x01) {
+                               dbg("SP%d No Interrupt !!!\n", i);
+                       } else {
+                               switch (sp[i] & 0x0f) {
+                               case SERIAL_IIR_RLS:
+                                       dbg("Serial Port %d: Receiver status error or ", i);
+                                       dbg("address bit detected in 9-bit mode\n");
+                                       mos7840_port->MsrLsr = 1;
+                                       mos7840_get_reg(mos7840_port, wval,
+                                                       LINE_STATUS_REGISTER,
+                                                       &Data);
+                                       break;
+                               case SERIAL_IIR_MS:
+                                       dbg("Serial Port %d: Modem status change\n", i);
+                                       mos7840_port->MsrLsr = 0;
+                                       mos7840_get_reg(mos7840_port, wval,
+                                                       MODEM_STATUS_REGISTER,
+                                                       &Data);
+                                       break;
+                               }
+                       }
+               }
+       }
+      exit:
+       result = usb_submit_urb(urb, GFP_ATOMIC);
+       if (result) {
+               dev_err(&urb->dev->dev,
+                       "%s - Error %d submitting interrupt urb\n",
+                       __FUNCTION__, result);
+       }
+
+       return;
+
+}
+
+static int mos7840_port_paranoia_check(struct usb_serial_port *port,
+                                      const char *function)
+{
+       if (!port) {
+               dbg("%s - port == NULL", function);
+               return -1;
+       }
+       if (!port->serial) {
+               dbg("%s - port->serial == NULL", function);
+               return -1;
+       }
+
+       return 0;
+}
+
+/* Inline functions to check the sanity of a pointer that is passed to us */
+static int mos7840_serial_paranoia_check(struct usb_serial *serial,
+                                        const char *function)
+{
+       if (!serial) {
+               dbg("%s - serial == NULL", function);
+               return -1;
+       }
+       if (!serial->type) {
+               dbg("%s - serial->type == NULL!", function);
+               return -1;
+       }
+
+       return 0;
+}
+
+static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port,
+                                                const char *function)
+{
+       /* if no port was specified, or it fails a paranoia check */
+       if (!port ||
+           mos7840_port_paranoia_check(port, function) ||
+           mos7840_serial_paranoia_check(port->serial, function)) {
+               /* then say that we don't have a valid usb_serial thing, which will                  * end up genrating -ENODEV return values */
+               return NULL;
+       }
+
+       return port->serial;
+}
+
+/*****************************************************************************
+ * mos7840_bulk_in_callback
+ *     this is the callback function for when we have received data on the
+ *     bulk in endpoint.
+ *****************************************************************************/
+
+static void mos7840_bulk_in_callback(struct urb *urb, struct pt_regs *regs)
+{
+       int status;
+       unsigned char *data;
+       struct usb_serial *serial;
+       struct usb_serial_port *port;
+       struct moschip_port *mos7840_port;
+       struct tty_struct *tty;
+
+       if (!urb) {
+               dbg("%s", "Invalid Pointer !!!!:\n");
+               return;
+       }
+
+       if (urb->status) {
+               dbg("nonzero read bulk status received: %d", urb->status);
+               return;
+       }
+
+       mos7840_port = (struct moschip_port *)urb->context;
+       if (!mos7840_port) {
+               dbg("%s", "NULL mos7840_port pointer \n");
+               return;
+       }
+
+       port = (struct usb_serial_port *)mos7840_port->port;
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return;
+       }
+
+       serial = mos7840_get_usb_serial(port, __FUNCTION__);
+       if (!serial) {
+               dbg("%s\n", "Bad serial pointer ");
+               return;
+       }
+
+       dbg("%s\n", "Entering... \n");
+
+       data = urb->transfer_buffer;
+
+       dbg("%s", "Entering ........... \n");
+
+       if (urb->actual_length) {
+               tty = mos7840_port->port->tty;
+               if (tty) {
+                       tty_buffer_request_room(tty, urb->actual_length);
+                       tty_insert_flip_string(tty, data, urb->actual_length);
+                       dbg(" %s \n", data);
+                       tty_flip_buffer_push(tty);
+               }
+               mos7840_port->icount.rx += urb->actual_length;
+               dbg("mos7840_port->icount.rx is %d:\n",
+                   mos7840_port->icount.rx);
+       }
+
+       if (!mos7840_port->read_urb) {
+               dbg("%s", "URB KILLED !!!\n");
+               return;
+       }
+
+       if (mos7840_port->read_urb->status != -EINPROGRESS) {
+               mos7840_port->read_urb->dev = serial->dev;
+
+               status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+
+               if (status) {
+                       dbg(" usb_submit_urb(read bulk) failed, status = %d",
+                           status);
+               }
+       }
+}
+
+/*****************************************************************************
+ * mos7840_bulk_out_data_callback
+ *     this is the callback function for when we have finished sending serial data
+ *     on the bulk out endpoint.
+ *****************************************************************************/
+
+static void mos7840_bulk_out_data_callback(struct urb *urb,
+                                          struct pt_regs *regs)
+{
+       struct moschip_port *mos7840_port;
+       struct tty_struct *tty;
+       if (!urb) {
+               dbg("%s", "Invalid Pointer !!!!:\n");
+               return;
+       }
+
+       if (urb->status) {
+               dbg("nonzero write bulk status received:%d\n", urb->status);
+               return;
+       }
+
+       mos7840_port = (struct moschip_port *)urb->context;
+       if (!mos7840_port) {
+               dbg("%s", "NULL mos7840_port pointer \n");
+               return;
+       }
+
+       if (mos7840_port_paranoia_check(mos7840_port->port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return;
+       }
+
+       dbg("%s \n", "Entering .........");
+
+       tty = mos7840_port->port->tty;
+
+       if (tty && mos7840_port->open) {
+               /* let the tty driver wakeup if it has a special *
+                * write_wakeup function                         */
+
+               if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
+                   && tty->ldisc.write_wakeup) {
+                       (tty->ldisc.write_wakeup) (tty);
+               }
+
+               /* tell the tty driver that something has changed */
+               wake_up_interruptible(&tty->write_wait);
+       }
+
+}
+
+/************************************************************************/
+/*       D R I V E R  T T Y  I N T E R F A C E  F U N C T I O N S       */
+/************************************************************************/
+#ifdef MCSSerialProbe
+static int mos7840_serial_probe(struct usb_serial *serial,
+                               const struct usb_device_id *id)
+{
+
+       /*need to implement the mode_reg reading and updating\
+          structures usb_serial_ device_type\
+          (i.e num_ports, num_bulkin,bulkout etc) */
+       /* Also we can update the changes  attach */
+       return 1;
+}
+#endif
+
+/*****************************************************************************
+ * mos7840_open
+ *     this function is called by the tty driver when a port is opened
+ *     If successful, we return 0
+ *     Otherwise we return a negative error number.
+ *****************************************************************************/
+
+static int mos7840_open(struct usb_serial_port *port, struct file *filp)
+{
+       int response;
+       int j;
+       struct usb_serial *serial;
+       struct urb *urb;
+       __u16 Data;
+       int status;
+       struct moschip_port *mos7840_port;
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return -ENODEV;
+       }
+
+       mos7840_num_open_ports++;
+       serial = port->serial;
+
+       if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+               dbg("%s", "Serial Paranoia failed \n");
+               return -ENODEV;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL)
+               return -ENODEV;
+
+       usb_clear_halt(serial->dev, port->write_urb->pipe);
+       usb_clear_halt(serial->dev, port->read_urb->pipe);
+
+       /* Initialising the write urb pool */
+       for (j = 0; j < NUM_URBS; ++j) {
+               urb = usb_alloc_urb(0, SLAB_ATOMIC);
+               mos7840_port->write_urb_pool[j] = urb;
+
+               if (urb == NULL) {
+                       err("No more urbs???");
+                       continue;
+               }
+
+               urb->transfer_buffer = NULL;
+               urb->transfer_buffer =
+                   kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+               if (!urb->transfer_buffer) {
+                       err("%s-out of memory for urb buffers.", __FUNCTION__);
+                       continue;
+               }
+       }
+
+/*****************************************************************************
+ * Initialize MCS7840 -- Write Init values to corresponding Registers
+ *
+ * Register Index
+ * 1 : IER
+ * 2 : FCR
+ * 3 : LCR
+ * 4 : MCR
+ *
+ * 0x08 : SP1/2 Control Reg
+ *****************************************************************************/
+
+//NEED to check the following Block
+
+       status = 0;
+       Data = 0x0;
+       status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
+       if (status < 0) {
+               dbg("Reading Spreg failed\n");
+               return -1;
+       }
+       Data |= 0x80;
+       status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+       if (status < 0) {
+               dbg("writing Spreg failed\n");
+               return -1;
+       }
+
+       Data &= ~0x80;
+       status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+       if (status < 0) {
+               dbg("writing Spreg failed\n");
+               return -1;
+       }
+//End of block to be checked
+
+       status = 0;
+       Data = 0x0;
+       status =
+           mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+       if (status < 0) {
+               dbg("Reading Controlreg failed\n");
+               return -1;
+       }
+       Data |= 0x08;           //Driver done bit
+       Data |= 0x20;           //rx_disable
+       status = 0;
+       status =
+           mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+       if (status < 0) {
+               dbg("writing Controlreg failed\n");
+               return -1;
+       }
+       //do register settings here
+       // Set all regs to the device default values.
+       ////////////////////////////////////
+       // First Disable all interrupts.
+       ////////////////////////////////////
+
+       Data = 0x00;
+       status = 0;
+       status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+       if (status < 0) {
+               dbg("disableing interrupts failed\n");
+               return -1;
+       }
+       // Set FIFO_CONTROL_REGISTER to the default value
+       Data = 0x00;
+       status = 0;
+       status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+       if (status < 0) {
+               dbg("Writing FIFO_CONTROL_REGISTER  failed\n");
+               return -1;
+       }
+
+       Data = 0xcf;
+       status = 0;
+       status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+       if (status < 0) {
+               dbg("Writing FIFO_CONTROL_REGISTER  failed\n");
+               return -1;
+       }
+
+       Data = 0x03;
+       status = 0;
+       status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+       mos7840_port->shadowLCR = Data;
+
+       Data = 0x0b;
+       status = 0;
+       status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+       mos7840_port->shadowMCR = Data;
+
+       Data = 0x00;
+       status = 0;
+       status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
+       mos7840_port->shadowLCR = Data;
+
+       Data |= SERIAL_LCR_DLAB;        //data latch enable in LCR 0x80
+       status = 0;
+       status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+       Data = 0x0c;
+       status = 0;
+       status = mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
+
+       Data = 0x0;
+       status = 0;
+       status = mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
+
+       Data = 0x00;
+       status = 0;
+       status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
+
+       Data = Data & ~SERIAL_LCR_DLAB;
+       status = 0;
+       status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+       mos7840_port->shadowLCR = Data;
+
+       //clearing Bulkin and Bulkout Fifo
+       Data = 0x0;
+       status = 0;
+       status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data);
+
+       Data = Data | 0x0c;
+       status = 0;
+       status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+
+       Data = Data & ~0x0c;
+       status = 0;
+       status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+       //Finally enable all interrupts
+       Data = 0x0;
+       Data = 0x0c;
+       status = 0;
+       status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+       //clearing rx_disable
+       Data = 0x0;
+       status = 0;
+       status =
+           mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+       Data = Data & ~0x20;
+       status = 0;
+       status =
+           mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+
+       // rx_negate
+       Data = 0x0;
+       status = 0;
+       status =
+           mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data);
+       Data = Data | 0x10;
+       status = 0;
+       status =
+           mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data);
+
+       /* force low_latency on so that our tty_push actually forces *
+        * the data through,otherwise it is scheduled, and with      *
+        * high data rates (like with OHCI) data can get lost.       */
+
+       if (port->tty)
+               port->tty->low_latency = 1;
+/* Check to see if we've set up our endpoint info yet    *
+     * (can't set it up in mos7840_startup as the structures *
+     * were not set up at that time.)                        */
+       if (mos7840_num_open_ports == 1) {
+               if (serial->port[0]->interrupt_in_buffer == NULL) {
+
+                       /* set up interrupt urb */
+
+                       usb_fill_int_urb(serial->port[0]->interrupt_in_urb,
+                                        serial->dev,
+                                        usb_rcvintpipe(serial->dev,
+                                                       serial->port[0]->
+                                                       interrupt_in_endpointAddress),
+                                        serial->port[0]->interrupt_in_buffer,
+                                        serial->port[0]->interrupt_in_urb->
+                                        transfer_buffer_length,
+                                        mos7840_interrupt_callback,
+                                        serial,
+                                        serial->port[0]->interrupt_in_urb->
+                                        interval);
+
+                       /* start interrupt read for mos7840               *
+                        * will continue as long as mos7840 is connected  */
+
+                       response =
+                           usb_submit_urb(serial->port[0]->interrupt_in_urb,
+                                          GFP_KERNEL);
+                       if (response) {
+                               err("%s - Error %d submitting interrupt urb",
+                                   __FUNCTION__, response);
+                       }
+
+               }
+
+       }
+
+       /* see if we've set up our endpoint info yet   *
+        * (can't set it up in mos7840_startup as the  *
+        * structures were not set up at that time.)   */
+
+       dbg("port number is %d \n", port->number);
+       dbg("serial number is %d \n", port->serial->minor);
+       dbg("Bulkin endpoint is %d \n", port->bulk_in_endpointAddress);
+       dbg("BulkOut endpoint is %d \n", port->bulk_out_endpointAddress);
+       dbg("Interrupt endpoint is %d \n", port->interrupt_in_endpointAddress);
+       dbg("port's number in the device is %d\n", mos7840_port->port_num);
+       mos7840_port->read_urb = port->read_urb;
+
+       /* set up our bulk in urb */
+
+       usb_fill_bulk_urb(mos7840_port->read_urb,
+                         serial->dev,
+                         usb_rcvbulkpipe(serial->dev,
+                                         port->bulk_in_endpointAddress),
+                         port->bulk_in_buffer,
+                         mos7840_port->read_urb->transfer_buffer_length,
+                         mos7840_bulk_in_callback, mos7840_port);
+
+       dbg("mos7840_open: bulkin endpoint is %d\n",
+           port->bulk_in_endpointAddress);
+       response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL);
+       if (response) {
+               err("%s - Error %d submitting control urb", __FUNCTION__,
+                   response);
+       }
+
+       /* initialize our wait queues */
+       init_waitqueue_head(&mos7840_port->wait_chase);
+       init_waitqueue_head(&mos7840_port->delta_msr_wait);
+
+       /* initialize our icount structure */
+       memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
+
+       /* initialize our port settings */
+       mos7840_port->shadowMCR = MCR_MASTER_IE;        /* Must set to enable ints! */
+       /* send a open port command */
+       mos7840_port->open = 1;
+       //mos7840_change_port_settings(mos7840_port,old_termios);
+       mos7840_port->icount.tx = 0;
+       mos7840_port->icount.rx = 0;
+
+       dbg("\n\nusb_serial serial:%x       mos7840_port:%x\n      usb_serial_port port:%x\n\n", (unsigned int)serial, (unsigned int)mos7840_port, (unsigned int)port);
+
+       return 0;
+
+}
+
+/*****************************************************************************
+ * mos7840_chars_in_buffer
+ *     this function is called by the tty driver when it wants to know how many
+ *     bytes of data we currently have outstanding in the port (data that has
+ *     been written, but hasn't made it out the port yet)
+ *     If successful, we return the number of bytes left to be written in the
+ *     system,
+ *     Otherwise we return a negative error number.
+ *****************************************************************************/
+
+static int mos7840_chars_in_buffer(struct usb_serial_port *port)
+{
+       int i;
+       int chars = 0;
+       struct moschip_port *mos7840_port;
+
+       dbg("%s \n", " mos7840_chars_in_buffer:entering ...........");
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return -1;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+       if (mos7840_port == NULL) {
+               dbg("%s \n", "mos7840_break:leaving ...........");
+               return -1;
+       }
+
+       for (i = 0; i < NUM_URBS; ++i) {
+               if (mos7840_port->write_urb_pool[i]->status == -EINPROGRESS) {
+                       chars += URB_TRANSFER_BUFFER_SIZE;
+               }
+       }
+       dbg("%s - returns %d", __FUNCTION__, chars);
+       return (chars);
+
+}
+
+/************************************************************************
+ *
+ * mos7840_block_until_tx_empty
+ *
+ *     This function will block the close until one of the following:
+ *             1. TX count are 0
+ *             2. The mos7840 has stopped
+ *             3. A timout of 3 seconds without activity has expired
+ *
+ ************************************************************************/
+static void mos7840_block_until_tx_empty(struct moschip_port *mos7840_port)
+{
+       int timeout = HZ / 10;
+       int wait = 30;
+       int count;
+
+       while (1) {
+
+               count = mos7840_chars_in_buffer(mos7840_port->port);
+
+               /* Check for Buffer status */
+               if (count <= 0) {
+                       return;
+               }
+
+               /* Block the thread for a while */
+               interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
+                                              timeout);
+
+               /* No activity.. count down section */
+               wait--;
+               if (wait == 0) {
+                       dbg("%s - TIMEOUT", __FUNCTION__);
+                       return;
+               } else {
+                       /* Reset timout value back to seconds */
+                       wait = 30;
+               }
+       }
+}
+
+/*****************************************************************************
+ * mos7840_close
+ *     this function is called by the tty driver when a port is closed
+ *****************************************************************************/
+
+static void mos7840_close(struct usb_serial_port *port, struct file *filp)
+{
+       struct usb_serial *serial;
+       struct moschip_port *mos7840_port;
+       int j;
+       __u16 Data;
+
+       dbg("%s\n", "mos7840_close:entering...");
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return;
+       }
+
+       serial = mos7840_get_usb_serial(port, __FUNCTION__);
+       if (!serial) {
+               dbg("%s", "Serial Paranoia failed \n");
+               return;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL) {
+               return;
+       }
+
+       for (j = 0; j < NUM_URBS; ++j)
+               usb_kill_urb(mos7840_port->write_urb_pool[j]);
+
+       /* Freeing Write URBs */
+       for (j = 0; j < NUM_URBS; ++j) {
+               if (mos7840_port->write_urb_pool[j]) {
+                       if (mos7840_port->write_urb_pool[j]->transfer_buffer)
+                               kfree(mos7840_port->write_urb_pool[j]->
+                                     transfer_buffer);
+
+                       usb_free_urb(mos7840_port->write_urb_pool[j]);
+               }
+       }
+
+       if (serial->dev) {
+               /* flush and block until tx is empty */
+               mos7840_block_until_tx_empty(mos7840_port);
+       }
+
+       /* While closing port, shutdown all bulk read, write  *
+        * and interrupt read if they exists                  */
+       if (serial->dev) {
+
+               if (mos7840_port->write_urb) {
+                       dbg("%s", "Shutdown bulk write\n");
+                       usb_kill_urb(mos7840_port->write_urb);
+               }
+
+               if (mos7840_port->read_urb) {
+                       dbg("%s", "Shutdown bulk read\n");
+                       usb_kill_urb(mos7840_port->read_urb);
+               }
+               if ((&mos7840_port->control_urb)) {
+                       dbg("%s", "Shutdown control read\n");
+                       //      usb_kill_urb (mos7840_port->control_urb);
+
+               }
+       }
+//              if(mos7840_port->ctrl_buf != NULL)
+//                      kfree(mos7840_port->ctrl_buf);
+       mos7840_num_open_ports--;
+       dbg("mos7840_num_open_ports in close%d:in port%d\n",
+           mos7840_num_open_ports, port->number);
+       if (mos7840_num_open_ports == 0) {
+               if (serial->port[0]->interrupt_in_urb) {
+                       dbg("%s", "Shutdown interrupt_in_urb\n");
+               }
+       }
+
+       if (mos7840_port->write_urb) {
+               /* if this urb had a transfer buffer already (old tx) free it */
+
+               if (mos7840_port->write_urb->transfer_buffer != NULL) {
+                       kfree(mos7840_port->write_urb->transfer_buffer);
+               }
+               usb_free_urb(mos7840_port->write_urb);
+       }
+
+       Data = 0x0;
+       mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+
+       Data = 0x00;
+       mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+       mos7840_port->open = 0;
+
+       dbg("%s \n", "Leaving ............");
+}
+
+/************************************************************************
+ *
+ * mos7840_block_until_chase_response
+ *
+ *     This function will block the close until one of the following:
+ *             1. Response to our Chase comes from mos7840
+ *             2. A timout of 10 seconds without activity has expired
+ *                (1K of mos7840 data @ 2400 baud ==> 4 sec to empty)
+ *
+ ************************************************************************/
+
+static void mos7840_block_until_chase_response(struct moschip_port
+                                              *mos7840_port)
+{
+       int timeout = 1 * HZ;
+       int wait = 10;
+       int count;
+
+       while (1) {
+               count = mos7840_chars_in_buffer(mos7840_port->port);
+
+               /* Check for Buffer status */
+               if (count <= 0) {
+                       return;
+               }
+
+               /* Block the thread for a while */
+               interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
+                                              timeout);
+               /* No activity.. count down section */
+               wait--;
+               if (wait == 0) {
+                       dbg("%s - TIMEOUT", __FUNCTION__);
+                       return;
+               } else {
+                       /* Reset timout value back to seconds */
+                       wait = 10;
+               }
+       }
+
+}
+
+/*****************************************************************************
+ * mos7840_break
+ *     this function sends a break to the port
+ *****************************************************************************/
+static void mos7840_break(struct usb_serial_port *port, int break_state)
+{
+       unsigned char data;
+       struct usb_serial *serial;
+       struct moschip_port *mos7840_port;
+
+       dbg("%s \n", "Entering ...........");
+       dbg("mos7840_break: Start\n");
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return;
+       }
+
+       serial = mos7840_get_usb_serial(port, __FUNCTION__);
+       if (!serial) {
+               dbg("%s", "Serial Paranoia failed \n");
+               return;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL) {
+               return;
+       }
+
+       if (serial->dev) {
+
+               /* flush and block until tx is empty */
+               mos7840_block_until_chase_response(mos7840_port);
+       }
+
+       if (break_state == -1) {
+               data = mos7840_port->shadowLCR | LCR_SET_BREAK;
+       } else {
+               data = mos7840_port->shadowLCR & ~LCR_SET_BREAK;
+       }
+
+       mos7840_port->shadowLCR = data;
+       dbg("mcs7840_break mos7840_port->shadowLCR is %x\n",
+           mos7840_port->shadowLCR);
+       mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER,
+                            mos7840_port->shadowLCR);
+
+       return;
+}
+
+/*****************************************************************************
+ * mos7840_write_room
+ *     this function is called by the tty driver when it wants to know how many
+ *     bytes of data we can accept for a specific port.
+ *     If successful, we return the amount of room that we have for this port
+ *     Otherwise we return a negative error number.
+ *****************************************************************************/
+
+static int mos7840_write_room(struct usb_serial_port *port)
+{
+       int i;
+       int room = 0;
+       struct moschip_port *mos7840_port;
+
+       dbg("%s \n", " mos7840_write_room:entering ...........");
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               dbg("%s \n", " mos7840_write_room:leaving ...........");
+               return -1;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+       if (mos7840_port == NULL) {
+               dbg("%s \n", "mos7840_break:leaving ...........");
+               return -1;
+       }
+
+       for (i = 0; i < NUM_URBS; ++i) {
+               if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) {
+                       room += URB_TRANSFER_BUFFER_SIZE;
+               }
+       }
+
+       dbg("%s - returns %d", __FUNCTION__, room);
+       return (room);
+
+}
+
+/*****************************************************************************
+ * mos7840_write
+ *     this function is called by the tty driver when data should be written to
+ *     the port.
+ *     If successful, we return the number of bytes written, otherwise we
+ *      return a negative error number.
+ *****************************************************************************/
+
+static int mos7840_write(struct usb_serial_port *port,
+                        const unsigned char *data, int count)
+{
+       int status;
+       int i;
+       int bytes_sent = 0;
+       int transfer_size;
+       int from_user = 0;
+
+       struct moschip_port *mos7840_port;
+       struct usb_serial *serial;
+       struct urb *urb;
+       //__u16 Data;
+       const unsigned char *current_position = data;
+       unsigned char *data1;
+       dbg("%s \n", "entering ...........");
+       //dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",mos7840_port->shadowLCR);
+
+#ifdef NOTMOS7840
+       Data = 0x00;
+       status = 0;
+       status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data);
+       mos7840_port->shadowLCR = Data;
+       dbg("mos7840_write: LINE_CONTROL_REGISTER is %x\n", Data);
+       dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
+           mos7840_port->shadowLCR);
+
+       //Data = 0x03;
+       //status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data);
+       //mos7840_port->shadowLCR=Data;//Need to add later
+
+       Data |= SERIAL_LCR_DLAB;        //data latch enable in LCR 0x80
+       status = 0;
+       status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+       //Data = 0x0c;
+       //status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data);
+       Data = 0x00;
+       status = 0;
+       status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data);
+       dbg("mos7840_write:DLL value is %x\n", Data);
+
+       Data = 0x0;
+       status = 0;
+       status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data);
+       dbg("mos7840_write:DLM value is %x\n", Data);
+
+       Data = Data & ~SERIAL_LCR_DLAB;
+       dbg("mos7840_write: mos7840_port->shadowLCR is %x\n",
+           mos7840_port->shadowLCR);
+       status = 0;
+       status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+#endif
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Port Paranoia failed \n");
+               return -1;
+       }
+
+       serial = port->serial;
+       if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+               dbg("%s", "Serial Paranoia failed \n");
+               return -1;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+       if (mos7840_port == NULL) {
+               dbg("%s", "mos7840_port is NULL\n");
+               return -1;
+       }
+
+       /* try to find a free urb in the list */
+       urb = NULL;
+
+       for (i = 0; i < NUM_URBS; ++i) {
+               if (mos7840_port->write_urb_pool[i]->status != -EINPROGRESS) {
+                       urb = mos7840_port->write_urb_pool[i];
+                       dbg("\nURB:%d", i);
+                       break;
+               }
+       }
+
+       if (urb == NULL) {
+               dbg("%s - no more free urbs", __FUNCTION__);
+               goto exit;
+       }
+
+       if (urb->transfer_buffer == NULL) {
+               urb->transfer_buffer =
+                   kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL);
+
+               if (urb->transfer_buffer == NULL) {
+                       err("%s no more kernel memory...", __FUNCTION__);
+                       goto exit;
+               }
+       }
+       transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE);
+
+       if (from_user) {
+               if (copy_from_user
+                   (urb->transfer_buffer, current_position, transfer_size)) {
+                       bytes_sent = -EFAULT;
+                       goto exit;
+               }
+       } else {
+               memcpy(urb->transfer_buffer, current_position, transfer_size);
+       }
+
+       /* fill urb with data and submit  */
+       usb_fill_bulk_urb(urb,
+                         serial->dev,
+                         usb_sndbulkpipe(serial->dev,
+                                         port->bulk_out_endpointAddress),
+                         urb->transfer_buffer,
+                         transfer_size,
+                         mos7840_bulk_out_data_callback, mos7840_port);
+
+       data1 = urb->transfer_buffer;
+       dbg("\nbulkout endpoint is %d", port->bulk_out_endpointAddress);
+
+       /* send it down the pipe */
+       status = usb_submit_urb(urb, GFP_ATOMIC);
+
+       if (status) {
+               err("%s - usb_submit_urb(write bulk) failed with status = %d",
+                   __FUNCTION__, status);
+               bytes_sent = status;
+               goto exit;
+       }
+       bytes_sent = transfer_size;
+       mos7840_port->icount.tx += transfer_size;
+       dbg("mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
+      exit:
+
+       return bytes_sent;
+
+}
+
+/*****************************************************************************
+ * mos7840_throttle
+ *     this function is called by the tty driver when it wants to stop the data
+ *     being read from the port.
+ *****************************************************************************/
+
+static void mos7840_throttle(struct usb_serial_port *port)
+{
+       struct moschip_port *mos7840_port;
+       struct tty_struct *tty;
+       int status;
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return;
+       }
+
+       dbg("- port %d\n", port->number);
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL)
+               return;
+
+       if (!mos7840_port->open) {
+               dbg("%s\n", "port not opened");
+               return;
+       }
+
+       dbg("%s", "Entering .......... \n");
+
+       tty = port->tty;
+       if (!tty) {
+               dbg("%s - no tty available", __FUNCTION__);
+               return;
+       }
+
+       /* if we are implementing XON/XOFF, send the stop character */
+       if (I_IXOFF(tty)) {
+               unsigned char stop_char = STOP_CHAR(tty);
+               status = mos7840_write(port, &stop_char, 1);
+               if (status <= 0) {
+                       return;
+               }
+       }
+
+       /* if we are implementing RTS/CTS, toggle that line */
+       if (tty->termios->c_cflag & CRTSCTS) {
+               mos7840_port->shadowMCR &= ~MCR_RTS;
+               status = 0;
+               status =
+                   mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+                                        mos7840_port->shadowMCR);
+
+               if (status < 0) {
+                       return;
+               }
+       }
+
+       return;
+}
+
+/*****************************************************************************
+ * mos7840_unthrottle
+ *     this function is called by the tty driver when it wants to resume the data
+ *     being read from the port (called after SerialThrottle is called)
+ *****************************************************************************/
+static void mos7840_unthrottle(struct usb_serial_port *port)
+{
+       struct tty_struct *tty;
+       int status;
+       struct moschip_port *mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return;
+       }
+
+       if (mos7840_port == NULL)
+               return;
+
+       if (!mos7840_port->open) {
+               dbg("%s - port not opened", __FUNCTION__);
+               return;
+       }
+
+       dbg("%s", "Entering .......... \n");
+
+       tty = port->tty;
+       if (!tty) {
+               dbg("%s - no tty available", __FUNCTION__);
+               return;
+       }
+
+       /* if we are implementing XON/XOFF, send the start character */
+       if (I_IXOFF(tty)) {
+               unsigned char start_char = START_CHAR(tty);
+               status = mos7840_write(port, &start_char, 1);
+               if (status <= 0) {
+                       return;
+               }
+       }
+
+       /* if we are implementing RTS/CTS, toggle that line */
+       if (tty->termios->c_cflag & CRTSCTS) {
+               mos7840_port->shadowMCR |= MCR_RTS;
+               status = 0;
+               status =
+                   mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
+                                        mos7840_port->shadowMCR);
+               if (status < 0) {
+                       return;
+               }
+       }
+
+       return;
+}
+
+static int mos7840_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+       struct moschip_port *mos7840_port;
+       unsigned int result;
+       __u16 msr;
+       __u16 mcr;
+       int status = 0;
+       mos7840_port = mos7840_get_port_private(port);
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       if (mos7840_port == NULL)
+               return -ENODEV;
+
+       status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr);
+       status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr);
+       result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)
+           | ((mcr & MCR_RTS) ? TIOCM_RTS : 0)
+           | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0)
+           | ((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0)
+           | ((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0)
+           | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)
+           | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0);
+
+       dbg("%s - 0x%04X", __FUNCTION__, result);
+
+       return result;
+}
+
+static int mos7840_tiocmset(struct usb_serial_port *port, struct file *file,
+                           unsigned int set, unsigned int clear)
+{
+       struct moschip_port *mos7840_port;
+       unsigned int mcr;
+       unsigned int status;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL)
+               return -ENODEV;
+
+       mcr = mos7840_port->shadowMCR;
+       if (clear & TIOCM_RTS)
+               mcr &= ~MCR_RTS;
+       if (clear & TIOCM_DTR)
+               mcr &= ~MCR_DTR;
+       if (clear & TIOCM_LOOP)
+               mcr &= ~MCR_LOOPBACK;
+
+       if (set & TIOCM_RTS)
+               mcr |= MCR_RTS;
+       if (set & TIOCM_DTR)
+               mcr |= MCR_DTR;
+       if (set & TIOCM_LOOP)
+               mcr |= MCR_LOOPBACK;
+
+       mos7840_port->shadowMCR = mcr;
+
+       status = 0;
+       status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr);
+       if (status < 0) {
+               dbg("setting MODEM_CONTROL_REGISTER Failed\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/*****************************************************************************
+ * mos7840_calc_baud_rate_divisor
+ *     this function calculates the proper baud rate divisor for the specified
+ *     baud rate.
+ *****************************************************************************/
+static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor,
+                                         __u16 * clk_sel_val)
+{
+
+       dbg("%s - %d", __FUNCTION__, baudRate);
+
+       if (baudRate <= 115200) {
+               *divisor = 115200 / baudRate;
+               *clk_sel_val = 0x0;
+       }
+       if ((baudRate > 115200) && (baudRate <= 230400)) {
+               *divisor = 230400 / baudRate;
+               *clk_sel_val = 0x10;
+       } else if ((baudRate > 230400) && (baudRate <= 403200)) {
+               *divisor = 403200 / baudRate;
+               *clk_sel_val = 0x20;
+       } else if ((baudRate > 403200) && (baudRate <= 460800)) {
+               *divisor = 460800 / baudRate;
+               *clk_sel_val = 0x30;
+       } else if ((baudRate > 460800) && (baudRate <= 806400)) {
+               *divisor = 806400 / baudRate;
+               *clk_sel_val = 0x40;
+       } else if ((baudRate > 806400) && (baudRate <= 921600)) {
+               *divisor = 921600 / baudRate;
+               *clk_sel_val = 0x50;
+       } else if ((baudRate > 921600) && (baudRate <= 1572864)) {
+               *divisor = 1572864 / baudRate;
+               *clk_sel_val = 0x60;
+       } else if ((baudRate > 1572864) && (baudRate <= 3145728)) {
+               *divisor = 3145728 / baudRate;
+               *clk_sel_val = 0x70;
+       }
+       return 0;
+
+#ifdef NOTMCS7840
+
+       for (i = 0; i < ARRAY_SIZE(mos7840_divisor_table); i++) {
+               if (mos7840_divisor_table[i].BaudRate == baudrate) {
+                       *divisor = mos7840_divisor_table[i].Divisor;
+                       return 0;
+               }
+       }
+
+       /* After trying for all the standard baud rates    *
+        * Try calculating the divisor for this baud rate  */
+
+       if (baudrate > 75 && baudrate < 230400) {
+               /* get the divisor */
+               custom = (__u16) (230400L / baudrate);
+
+               /* Check for round off */
+               round1 = (__u16) (2304000L / baudrate);
+               round = (__u16) (round1 - (custom * 10));
+               if (round > 4) {
+                       custom++;
+               }
+               *divisor = custom;
+
+               dbg(" Baud %d = %d\n", baudrate, custom);
+               return 0;
+       }
+
+       dbg("%s\n", " Baud calculation Failed...");
+       return -1;
+#endif
+}
+
+/*****************************************************************************
+ * mos7840_send_cmd_write_baud_rate
+ *     this function sends the proper command to change the baud rate of the
+ *     specified port.
+ *****************************************************************************/
+
+static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
+                                           int baudRate)
+{
+       int divisor = 0;
+       int status;
+       __u16 Data;
+       unsigned char number;
+       __u16 clk_sel_val;
+       struct usb_serial_port *port;
+
+       if (mos7840_port == NULL)
+               return -1;
+
+       port = (struct usb_serial_port *)mos7840_port->port;
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return -1;
+       }
+
+       if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
+               dbg("%s", "Invalid Serial \n");
+               return -1;
+       }
+
+       dbg("%s", "Entering .......... \n");
+
+       number = mos7840_port->port->number - mos7840_port->port->serial->minor;
+
+       dbg("%s - port = %d, baud = %d", __FUNCTION__,
+           mos7840_port->port->number, baudRate);
+       //reset clk_uart_sel in spregOffset
+       if (baudRate > 115200) {
+#ifdef HW_flow_control
+               //NOTE: need to see the pther register to modify
+               //setting h/w flow control bit to 1;
+               status = 0;
+               Data = 0x2b;
+               mos7840_port->shadowMCR = Data;
+               status =
+                   mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+               if (status < 0) {
+                       dbg("Writing spreg failed in set_serial_baud\n");
+                       return -1;
+               }
+#endif
+
+       } else {
+#ifdef HW_flow_control
+               //setting h/w flow control bit to 0;
+               status = 0;
+               Data = 0xb;
+               mos7840_port->shadowMCR = Data;
+               status =
+                   mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+               if (status < 0) {
+                       dbg("Writing spreg failed in set_serial_baud\n");
+                       return -1;
+               }
+#endif
+
+       }
+
+       if (1)                  //baudRate <= 115200)
+       {
+               clk_sel_val = 0x0;
+               Data = 0x0;
+               status = 0;
+               status =
+                   mos7840_calc_baud_rate_divisor(baudRate, &divisor,
+                                                  &clk_sel_val);
+               status =
+                   mos7840_get_reg_sync(port, mos7840_port->SpRegOffset,
+                                        &Data);
+               if (status < 0) {
+                       dbg("reading spreg failed in set_serial_baud\n");
+                       return -1;
+               }
+               Data = (Data & 0x8f) | clk_sel_val;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data);
+               if (status < 0) {
+                       dbg("Writing spreg failed in set_serial_baud\n");
+                       return -1;
+               }
+               /* Calculate the Divisor */
+
+               if (status) {
+                       err("%s - bad baud rate", __FUNCTION__);
+                       dbg("%s\n", "bad baud rate");
+                       return status;
+               }
+               /* Enable access to divisor latch */
+               Data = mos7840_port->shadowLCR | SERIAL_LCR_DLAB;
+               mos7840_port->shadowLCR = Data;
+               mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+               /* Write the divisor */
+               Data = (unsigned char)(divisor & 0xff);
+               dbg("set_serial_baud Value to write DLL is %x\n", Data);
+               mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data);
+
+               Data = (unsigned char)((divisor & 0xff00) >> 8);
+               dbg("set_serial_baud Value to write DLM is %x\n", Data);
+               mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data);
+
+               /* Disable access to divisor latch */
+               Data = mos7840_port->shadowLCR & ~SERIAL_LCR_DLAB;
+               mos7840_port->shadowLCR = Data;
+               mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+       }
+
+       return status;
+}
+
+/*****************************************************************************
+ * mos7840_change_port_settings
+ *     This routine is called to set the UART on the device to match
+ *      the specified new settings.
+ *****************************************************************************/
+
+static void mos7840_change_port_settings(struct moschip_port *mos7840_port,
+                                        struct termios *old_termios)
+{
+       struct tty_struct *tty;
+       int baud;
+       unsigned cflag;
+       unsigned iflag;
+       __u8 lData;
+       __u8 lParity;
+       __u8 lStop;
+       int status;
+       __u16 Data;
+       struct usb_serial_port *port;
+       struct usb_serial *serial;
+
+       if (mos7840_port == NULL)
+               return;
+
+       port = (struct usb_serial_port *)mos7840_port->port;
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return;
+       }
+
+       if (mos7840_serial_paranoia_check(port->serial, __FUNCTION__)) {
+               dbg("%s", "Invalid Serial \n");
+               return;
+       }
+
+       serial = port->serial;
+
+       dbg("%s - port %d", __FUNCTION__, mos7840_port->port->number);
+
+       if (!mos7840_port->open) {
+               dbg("%s - port not opened", __FUNCTION__);
+               return;
+       }
+
+       tty = mos7840_port->port->tty;
+
+       if ((!tty) || (!tty->termios)) {
+               dbg("%s - no tty structures", __FUNCTION__);
+               return;
+       }
+
+       dbg("%s", "Entering .......... \n");
+
+       lData = LCR_BITS_8;
+       lStop = LCR_STOP_1;
+       lParity = LCR_PAR_NONE;
+
+       cflag = tty->termios->c_cflag;
+       iflag = tty->termios->c_iflag;
+
+       /* Change the number of bits */
+       if (cflag & CSIZE) {
+               switch (cflag & CSIZE) {
+               case CS5:
+                       lData = LCR_BITS_5;
+                       break;
+
+               case CS6:
+                       lData = LCR_BITS_6;
+                       break;
+
+               case CS7:
+                       lData = LCR_BITS_7;
+                       break;
+               default:
+               case CS8:
+                       lData = LCR_BITS_8;
+                       break;
+               }
+       }
+       /* Change the Parity bit */
+       if (cflag & PARENB) {
+               if (cflag & PARODD) {
+                       lParity = LCR_PAR_ODD;
+                       dbg("%s - parity = odd", __FUNCTION__);
+               } else {
+                       lParity = LCR_PAR_EVEN;
+                       dbg("%s - parity = even", __FUNCTION__);
+               }
+
+       } else {
+               dbg("%s - parity = none", __FUNCTION__);
+       }
+
+       if (cflag & CMSPAR) {
+               lParity = lParity | 0x20;
+       }
+
+       /* Change the Stop bit */
+       if (cflag & CSTOPB) {
+               lStop = LCR_STOP_2;
+               dbg("%s - stop bits = 2", __FUNCTION__);
+       } else {
+               lStop = LCR_STOP_1;
+               dbg("%s - stop bits = 1", __FUNCTION__);
+       }
+
+       /* Update the LCR with the correct value */
+       mos7840_port->shadowLCR &=
+           ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK);
+       mos7840_port->shadowLCR |= (lData | lParity | lStop);
+
+       dbg("mos7840_change_port_settings mos7840_port->shadowLCR is %x\n",
+           mos7840_port->shadowLCR);
+       /* Disable Interrupts */
+       Data = 0x00;
+       mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+       Data = 0x00;
+       mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+
+       Data = 0xcf;
+       mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data);
+
+       /* Send the updated LCR value to the mos7840 */
+       Data = mos7840_port->shadowLCR;
+
+       mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data);
+
+       Data = 0x00b;
+       mos7840_port->shadowMCR = Data;
+       mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+       Data = 0x00b;
+       mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+
+       /* set up the MCR register and send it to the mos7840 */
+
+       mos7840_port->shadowMCR = MCR_MASTER_IE;
+       if (cflag & CBAUD) {
+               mos7840_port->shadowMCR |= (MCR_DTR | MCR_RTS);
+       }
+
+       if (cflag & CRTSCTS) {
+               mos7840_port->shadowMCR |= (MCR_XON_ANY);
+
+       } else {
+               mos7840_port->shadowMCR &= ~(MCR_XON_ANY);
+       }
+
+       Data = mos7840_port->shadowMCR;
+       mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+
+       /* Determine divisor based on baud rate */
+       baud = tty_get_baud_rate(tty);
+
+       if (!baud) {
+               /* pick a default, any default... */
+               dbg("%s\n", "Picked default baud...");
+               baud = 9600;
+       }
+
+       dbg("%s - baud rate = %d", __FUNCTION__, baud);
+       status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud);
+
+       /* Enable Interrupts */
+       Data = 0x0c;
+       mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);
+
+       if (mos7840_port->read_urb->status != -EINPROGRESS) {
+               mos7840_port->read_urb->dev = serial->dev;
+
+               status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+
+               if (status) {
+                       dbg(" usb_submit_urb(read bulk) failed, status = %d",
+                           status);
+               }
+       }
+       wake_up(&mos7840_port->delta_msr_wait);
+       mos7840_port->delta_msr_cond = 1;
+       dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x\n",
+           mos7840_port->shadowLCR);
+
+       return;
+}
+
+/*****************************************************************************
+ * mos7840_set_termios
+ *     this function is called by the tty driver when it wants to change
+ *     the termios structure
+ *****************************************************************************/
+
+static void mos7840_set_termios(struct usb_serial_port *port,
+                               struct termios *old_termios)
+{
+       int status;
+       unsigned int cflag;
+       struct usb_serial *serial;
+       struct moschip_port *mos7840_port;
+       struct tty_struct *tty;
+       dbg("mos7840_set_termios: START\n");
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return;
+       }
+
+       serial = port->serial;
+
+       if (mos7840_serial_paranoia_check(serial, __FUNCTION__)) {
+               dbg("%s", "Invalid Serial \n");
+               return;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+
+       if (mos7840_port == NULL)
+               return;
+
+       tty = port->tty;
+
+       if (!port->tty || !port->tty->termios) {
+               dbg("%s - no tty or termios", __FUNCTION__);
+               return;
+       }
+
+       if (!mos7840_port->open) {
+               dbg("%s - port not opened", __FUNCTION__);
+               return;
+       }
+
+       dbg("%s\n", "setting termios - ");
+
+       cflag = tty->termios->c_cflag;
+
+       if (!cflag) {
+               dbg("%s %s\n", __FUNCTION__, "cflag is NULL");
+               return;
+       }
+
+       /* check that they really want us to change something */
+       if (old_termios) {
+               if ((cflag == old_termios->c_cflag) &&
+                   (RELEVANT_IFLAG(tty->termios->c_iflag) ==
+                    RELEVANT_IFLAG(old_termios->c_iflag))) {
+                       dbg("%s\n", "Nothing to change");
+                       return;
+               }
+       }
+
+       dbg("%s - clfag %08x iflag %08x", __FUNCTION__,
+           tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag));
+
+       if (old_termios) {
+               dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__,
+                   old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag));
+       }
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* change the port settings to the new ones specified */
+
+       mos7840_change_port_settings(mos7840_port, old_termios);
+
+       if (!mos7840_port->read_urb) {
+               dbg("%s", "URB KILLED !!!!!\n");
+               return;
+       }
+
+       if (mos7840_port->read_urb->status != -EINPROGRESS) {
+               mos7840_port->read_urb->dev = serial->dev;
+               status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
+               if (status) {
+                       dbg(" usb_submit_urb(read bulk) failed, status = %d",
+                           status);
+               }
+       }
+       return;
+}
+
+/*****************************************************************************
+ * mos7840_get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ *         is emptied.  On bus types like RS485, the transmitter must
+ *         release the bus after transmitting. This must be done when
+ *         the transmit shift register is empty, not be done when the
+ *         transmit holding register is empty.  This functionality
+ *         allows an RS485 driver to be written in user space.
+ *****************************************************************************/
+
+static int mos7840_get_lsr_info(struct moschip_port *mos7840_port,
+                               unsigned int *value)
+{
+       int count;
+       unsigned int result = 0;
+
+       count = mos7840_chars_in_buffer(mos7840_port->port);
+       if (count == 0) {
+               dbg("%s -- Empty", __FUNCTION__);
+               result = TIOCSER_TEMT;
+       }
+
+       if (copy_to_user(value, &result, sizeof(int)))
+               return -EFAULT;
+       return 0;
+}
+
+/*****************************************************************************
+ * mos7840_get_bytes_avail - get number of bytes available
+ *
+ * Purpose: Let user call ioctl to get the count of number of bytes available.
+ *****************************************************************************/
+
+static int mos7840_get_bytes_avail(struct moschip_port *mos7840_port,
+                                  unsigned int *value)
+{
+       unsigned int result = 0;
+       struct tty_struct *tty = mos7840_port->port->tty;
+
+       if (!tty)
+               return -ENOIOCTLCMD;
+
+       result = tty->read_cnt;
+
+       dbg("%s(%d) = %d", __FUNCTION__, mos7840_port->port->number, result);
+       if (copy_to_user(value, &result, sizeof(int)))
+               return -EFAULT;
+
+       return -ENOIOCTLCMD;
+}
+
+/*****************************************************************************
+ * mos7840_set_modem_info
+ *      function to set modem info
+ *****************************************************************************/
+
+static int mos7840_set_modem_info(struct moschip_port *mos7840_port,
+                                 unsigned int cmd, unsigned int *value)
+{
+       unsigned int mcr;
+       unsigned int arg;
+       __u16 Data;
+       int status;
+       struct usb_serial_port *port;
+
+       if (mos7840_port == NULL)
+               return -1;
+
+       port = (struct usb_serial_port *)mos7840_port->port;
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return -1;
+       }
+
+       mcr = mos7840_port->shadowMCR;
+
+       if (copy_from_user(&arg, value, sizeof(int)))
+               return -EFAULT;
+
+       switch (cmd) {
+       case TIOCMBIS:
+               if (arg & TIOCM_RTS)
+                       mcr |= MCR_RTS;
+               if (arg & TIOCM_DTR)
+                       mcr |= MCR_RTS;
+               if (arg & TIOCM_LOOP)
+                       mcr |= MCR_LOOPBACK;
+               break;
+
+       case TIOCMBIC:
+               if (arg & TIOCM_RTS)
+                       mcr &= ~MCR_RTS;
+               if (arg & TIOCM_DTR)
+                       mcr &= ~MCR_RTS;
+               if (arg & TIOCM_LOOP)
+                       mcr &= ~MCR_LOOPBACK;
+               break;
+
+       case TIOCMSET:
+               /* turn off the RTS and DTR and LOOPBACK
+                * and then only turn on what was asked to */
+               mcr &= ~(MCR_RTS | MCR_DTR | MCR_LOOPBACK);
+               mcr |= ((arg & TIOCM_RTS) ? MCR_RTS : 0);
+               mcr |= ((arg & TIOCM_DTR) ? MCR_DTR : 0);
+               mcr |= ((arg & TIOCM_LOOP) ? MCR_LOOPBACK : 0);
+               break;
+       }
+
+       mos7840_port->shadowMCR = mcr;
+
+       Data = mos7840_port->shadowMCR;
+       status = 0;
+       status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data);
+       if (status < 0) {
+               dbg("setting MODEM_CONTROL_REGISTER Failed\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+/*****************************************************************************
+ * mos7840_get_modem_info
+ *      function to get modem info
+ *****************************************************************************/
+
+static int mos7840_get_modem_info(struct moschip_port *mos7840_port,
+                                 unsigned int *value)
+{
+       unsigned int result = 0;
+       __u16 msr;
+       unsigned int mcr = mos7840_port->shadowMCR;
+       int status = 0;
+       status =
+           mos7840_get_uart_reg(mos7840_port->port, MODEM_STATUS_REGISTER,
+                                &msr);
+       result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0)      /* 0x002 */
+           |((mcr & MCR_RTS) ? TIOCM_RTS : 0)  /* 0x004 */
+           |((msr & MOS7840_MSR_CTS) ? TIOCM_CTS : 0)  /* 0x020 */
+           |((msr & MOS7840_MSR_CD) ? TIOCM_CAR : 0)   /* 0x040 */
+           |((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0)    /* 0x080 */
+           |((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */
+
+       dbg("%s -- %x", __FUNCTION__, result);
+
+       if (copy_to_user(value, &result, sizeof(int)))
+               return -EFAULT;
+       return 0;
+}
+
+/*****************************************************************************
+ * mos7840_get_serial_info
+ *      function to get information about serial port
+ *****************************************************************************/
+
+static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
+                                  struct serial_struct *retinfo)
+{
+       struct serial_struct tmp;
+
+       if (mos7840_port == NULL)
+               return -1;
+
+       if (!retinfo)
+               return -EFAULT;
+
+       memset(&tmp, 0, sizeof(tmp));
+
+       tmp.type = PORT_16550A;
+       tmp.line = mos7840_port->port->serial->minor;
+       tmp.port = mos7840_port->port->number;
+       tmp.irq = 0;
+       tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+       tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE;
+       tmp.baud_base = 9600;
+       tmp.close_delay = 5 * HZ;
+       tmp.closing_wait = 30 * HZ;
+
+       if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+               return -EFAULT;
+       return 0;
+}
+
+/*****************************************************************************
+ * SerialIoctl
+ *     this function handles any ioctl calls to the driver
+ *****************************************************************************/
+
+static int mos7840_ioctl(struct usb_serial_port *port, struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+       struct moschip_port *mos7840_port;
+       struct tty_struct *tty;
+
+       struct async_icount cnow;
+       struct async_icount cprev;
+       struct serial_icounter_struct icount;
+       int mosret = 0;
+       int retval;
+       struct tty_ldisc *ld;
+
+       if (mos7840_port_paranoia_check(port, __FUNCTION__)) {
+               dbg("%s", "Invalid port \n");
+               return -1;
+       }
+
+       mos7840_port = mos7840_get_port_private(port);
+       tty = mos7840_port->port->tty;
+
+       if (mos7840_port == NULL)
+               return -1;
+
+       dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
+
+       switch (cmd) {
+               /* return number of bytes available */
+
+       case TIOCINQ:
+               dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number);
+               return mos7840_get_bytes_avail(mos7840_port,
+                                              (unsigned int *)arg);
+               break;
+
+       case TIOCOUTQ:
+               dbg("%s (%d) TIOCOUTQ", __FUNCTION__, port->number);
+               return put_user(tty->driver->chars_in_buffer ?
+                               tty->driver->chars_in_buffer(tty) : 0,
+                               (int __user *)arg);
+               break;
+
+       case TCFLSH:
+               retval = tty_check_change(tty);
+               if (retval)
+                       return retval;
+
+               ld = tty_ldisc_ref(tty);
+               switch (arg) {
+               case TCIFLUSH:
+                       if (ld && ld->flush_buffer)
+                               ld->flush_buffer(tty);
+                       break;
+               case TCIOFLUSH:
+                       if (ld && ld->flush_buffer)
+                               ld->flush_buffer(tty);
+                       /* fall through */
+               case TCOFLUSH:
+                       if (tty->driver->flush_buffer)
+                               tty->driver->flush_buffer(tty);
+                       break;
+               default:
+                       tty_ldisc_deref(ld);
+                       return -EINVAL;
+               }
+               tty_ldisc_deref(ld);
+               return 0;
+
+       case TCGETS:
+               if (kernel_termios_to_user_termios
+                   ((struct termios __user *)arg, tty->termios))
+                       return -EFAULT;
+               return 0;
+
+       case TIOCSERGETLSR:
+               dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number);
+               return mos7840_get_lsr_info(mos7840_port, (unsigned int *)arg);
+               return 0;
+
+       case TIOCMBIS:
+       case TIOCMBIC:
+       case TIOCMSET:
+               dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,
+                   port->number);
+               mosret =
+                   mos7840_set_modem_info(mos7840_port, cmd,
+                                          (unsigned int *)arg);
+               return mosret;
+
+       case TIOCMGET:
+               dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
+               return mos7840_get_modem_info(mos7840_port,
+                                             (unsigned int *)arg);
+
+       case TIOCGSERIAL:
+               dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number);
+               return mos7840_get_serial_info(mos7840_port,
+                                              (struct serial_struct *)arg);
+
+       case TIOCSSERIAL:
+               dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number);
+               break;
+
+       case TIOCMIWAIT:
+               dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number);
+               cprev = mos7840_port->icount;
+               while (1) {
+                       //interruptible_sleep_on(&mos7840_port->delta_msr_wait);
+                       mos7840_port->delta_msr_cond = 0;
+                       wait_event_interruptible(mos7840_port->delta_msr_wait,
+                                                (mos7840_port->
+                                                 delta_msr_cond == 1));
+
+                       /* see if a signal did it */
+                       if (signal_pending(current))
+                               return -ERESTARTSYS;
+                       cnow = mos7840_port->icount;
+                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+                               return -EIO;    /* no change => error */
+                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+                           ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
+                               return 0;
+                       }
+                       cprev = cnow;
+               }
+               /* NOTREACHED */
+               break;
+
+       case TIOCGICOUNT:
+               cnow = mos7840_port->icount;
+               icount.cts = cnow.cts;
+               icount.dsr = cnow.dsr;
+               icount.rng = cnow.rng;
+               icount.dcd = cnow.dcd;
+               icount.rx = cnow.rx;
+               icount.tx = cnow.tx;
+               icount.frame = cnow.frame;
+               icount.overrun = cnow.overrun;
+               icount.parity = cnow.parity;
+               icount.brk = cnow.brk;
+               icount.buf_overrun = cnow.buf_overrun;
+
+               dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__,
+                   port->number, icount.rx, icount.tx);
+               if (copy_to_user((void *)arg, &icount, sizeof(icount)))
+                       return -EFAULT;
+               return 0;
+
+       case TIOCEXBAUD:
+               return 0;
+       default:
+               break;
+       }
+
+       return -ENOIOCTLCMD;
+}
+
+static int mos7840_calc_num_ports(struct usb_serial *serial)
+{
+
+       dbg("numberofendpoints: %d \n",
+           (int)serial->interface->cur_altsetting->desc.bNumEndpoints);
+       dbg("numberofendpoints: %d \n",
+           (int)serial->interface->altsetting->desc.bNumEndpoints);
+       if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
+               mos7840_num_ports = 2;
+               serial->type->num_ports = 2;
+       } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
+               mos7840_num_ports = 4;
+               serial->type->num_bulk_in = 4;
+               serial->type->num_bulk_out = 4;
+               serial->type->num_ports = 4;
+       }
+
+       return mos7840_num_ports;
+}
+
+/****************************************************************************
+ * mos7840_startup
+ ****************************************************************************/
+
+static int mos7840_startup(struct usb_serial *serial)
+{
+       struct moschip_port *mos7840_port;
+       struct usb_device *dev;
+       int i, status;
+
+       __u16 Data;
+       dbg("%s \n", " mos7840_startup :entering..........");
+
+       if (!serial) {
+               dbg("%s\n", "Invalid Handler");
+               return -1;
+       }
+
+       dev = serial->dev;
+
+       dbg("%s\n", "Entering...");
+
+       /* we set up the pointers to the endpoints in the mos7840_open *
+        * function, as the structures aren't created yet.             */
+
+       /* set up port private structures */
+       for (i = 0; i < serial->num_ports; ++i) {
+               mos7840_port = kmalloc(sizeof(struct moschip_port), GFP_KERNEL);
+               if (mos7840_port == NULL) {
+                       err("%s - Out of memory", __FUNCTION__);
+                       return -ENOMEM;
+               }
+               memset(mos7840_port, 0, sizeof(struct moschip_port));
+
+               /* Initialize all port interrupt end point to port 0 int endpoint *
+                * Our device has only one interrupt end point comman to all port */
+
+               mos7840_port->port = serial->port[i];
+               mos7840_set_port_private(serial->port[i], mos7840_port);
+
+               mos7840_port->port_num = ((serial->port[i]->number -
+                                          (serial->port[i]->serial->minor)) +
+                                         1);
+
+               if (mos7840_port->port_num == 1) {
+                       mos7840_port->SpRegOffset = 0x0;
+                       mos7840_port->ControlRegOffset = 0x1;
+                       mos7840_port->DcrRegOffset = 0x4;
+               } else if ((mos7840_port->port_num == 2)
+                          && (mos7840_num_ports == 4)) {
+                       mos7840_port->SpRegOffset = 0x8;
+                       mos7840_port->ControlRegOffset = 0x9;
+                       mos7840_port->DcrRegOffset = 0x16;
+               } else if ((mos7840_port->port_num == 2)
+                          && (mos7840_num_ports == 2)) {
+                       mos7840_port->SpRegOffset = 0xa;
+                       mos7840_port->ControlRegOffset = 0xb;
+                       mos7840_port->DcrRegOffset = 0x19;
+               } else if ((mos7840_port->port_num == 3)
+                          && (mos7840_num_ports == 4)) {
+                       mos7840_port->SpRegOffset = 0xa;
+                       mos7840_port->ControlRegOffset = 0xb;
+                       mos7840_port->DcrRegOffset = 0x19;
+               } else if ((mos7840_port->port_num == 4)
+                          && (mos7840_num_ports == 4)) {
+                       mos7840_port->SpRegOffset = 0xc;
+                       mos7840_port->ControlRegOffset = 0xd;
+                       mos7840_port->DcrRegOffset = 0x1c;
+               }
+               mos7840_dump_serial_port(mos7840_port);
+
+               mos7840_set_port_private(serial->port[i], mos7840_port);
+
+               //enable rx_disable bit in control register
+
+               status =
+                   mos7840_get_reg_sync(serial->port[i],
+                                        mos7840_port->ControlRegOffset, &Data);
+               if (status < 0) {
+                       dbg("Reading ControlReg failed status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("ControlReg Reading success val is %x, status%d\n",
+                           Data, status);
+               Data |= 0x08;   //setting driver done bit
+               Data |= 0x04;   //sp1_bit to have cts change reflect in modem status reg
+
+               //Data |= 0x20; //rx_disable bit
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i],
+                                        mos7840_port->ControlRegOffset, Data);
+               if (status < 0) {
+                       dbg("Writing ControlReg failed(rx_disable) status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("ControlReg Writing success(rx_disable) status%d\n",
+                           status);
+
+               //Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 and 0x24 in DCR3
+               Data = 0x01;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i],
+                                        (__u16) (mos7840_port->DcrRegOffset +
+                                                 0), Data);
+               if (status < 0) {
+                       dbg("Writing DCR0 failed status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("DCR0 Writing success status%d\n", status);
+
+               Data = 0x05;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i],
+                                        (__u16) (mos7840_port->DcrRegOffset +
+                                                 1), Data);
+               if (status < 0) {
+                       dbg("Writing DCR1 failed status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("DCR1 Writing success status%d\n", status);
+
+               Data = 0x24;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i],
+                                        (__u16) (mos7840_port->DcrRegOffset +
+                                                 2), Data);
+               if (status < 0) {
+                       dbg("Writing DCR2 failed status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("DCR2 Writing success status%d\n", status);
+
+               // write values in clkstart0x0 and clkmulti 0x20
+               Data = 0x0;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i],
+                                        CLK_START_VALUE_REGISTER, Data);
+               if (status < 0) {
+                       dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
+                       break;
+               } else
+                       dbg("CLK_START_VALUE_REGISTER Writing success status%d\n", status);
+
+               Data = 0x20;
+               status = 0;
+               status =
+                   mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER,
+                                        Data);
+               if (status < 0) {
+                       dbg("Writing CLK_MULTI_REGISTER failed status-0x%x\n",
+                           status);
+                       break;
+               } else
+                       dbg("CLK_MULTI_REGISTER Writing success status%d\n",
+                           status);
+
+               //write value 0x0 to scratchpad register
+               Data = 0x00;
+               status = 0;
+               status =
+                   mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER,
+                                        Data);
+               if (status < 0) {
+                       dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x\n",
+                           status);
+                       break;
+               } else
+                       dbg("SCRATCH_PAD_REGISTER Writing success status%d\n",
+                           status);
+
+               //Zero Length flag register
+               if ((mos7840_port->port_num != 1)
+                   && (mos7840_num_ports == 2)) {
+
+                       Data = 0xff;
+                       status = 0;
+                       status = mos7840_set_reg_sync(serial->port[i],
+                                                     (__u16) (ZLP_REG1 +
+                                                              ((__u16)
+                                                               mos7840_port->
+                                                               port_num)),
+                                                     Data);
+                       dbg("ZLIP offset%x\n",
+                           (__u16) (ZLP_REG1 +
+                                    ((__u16) mos7840_port->port_num)));
+                       if (status < 0) {
+                               dbg("Writing ZLP_REG%d failed status-0x%x\n",
+                                   i + 2, status);
+                               break;
+                       } else
+                               dbg("ZLP_REG%d Writing success status%d\n",
+                                   i + 2, status);
+               } else {
+                       Data = 0xff;
+                       status = 0;
+                       status = mos7840_set_reg_sync(serial->port[i],
+                                                     (__u16) (ZLP_REG1 +
+                                                              ((__u16)
+                                                               mos7840_port->
+                                                               port_num) -
+                                                              0x1), Data);
+                       dbg("ZLIP offset%x\n",
+                           (__u16) (ZLP_REG1 +
+                                    ((__u16) mos7840_port->port_num) - 0x1));
+                       if (status < 0) {
+                               dbg("Writing ZLP_REG%d failed status-0x%x\n",
+                                   i + 1, status);
+                               break;
+                       } else
+                               dbg("ZLP_REG%d Writing success status%d\n",
+                                   i + 1, status);
+
+               }
+               mos7840_port->control_urb = usb_alloc_urb(0, SLAB_ATOMIC);
+               mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
+
+       }
+
+       //Zero Length flag enable
+       Data = 0x0f;
+       status = 0;
+       status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
+       if (status < 0) {
+               dbg("Writing ZLP_REG5 failed status-0x%x\n", status);
+               return -1;
+       } else
+               dbg("ZLP_REG5 Writing success status%d\n", status);
+
+       /* setting configuration feature to one */
+       usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                       (__u8) 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 5 * HZ);
+       return 0;
+}
+
+/****************************************************************************
+ * mos7840_shutdown
+ *     This function is called whenever the device is removed from the usb bus.
+ ****************************************************************************/
+
+static void mos7840_shutdown(struct usb_serial *serial)
+{
+       int i;
+       struct moschip_port *mos7840_port;
+       dbg("%s \n", " shutdown :entering..........");
+
+       if (!serial) {
+               dbg("%s", "Invalid Handler \n");
+               return;
+       }
+
+       /*      check for the ports to be closed,close the ports and disconnect         */
+
+       /* free private structure allocated for serial port  *
+        * stop reads and writes on all ports                */
+
+       for (i = 0; i < serial->num_ports; ++i) {
+               mos7840_port = mos7840_get_port_private(serial->port[i]);
+               kfree(mos7840_port->ctrl_buf);
+               usb_kill_urb(mos7840_port->control_urb);
+               kfree(mos7840_port);
+               mos7840_set_port_private(serial->port[i], NULL);
+       }
+
+       dbg("%s\n", "Thank u :: ");
+
+}
+
+static struct usb_serial_driver moschip7840_4port_device = {
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "mos7840",
+                  },
+       .description = DRIVER_DESC,
+       .id_table = moschip_port_id_table,
+       .num_interrupt_in = 1,  //NUM_DONT_CARE,//1,
+#ifdef check
+       .num_bulk_in = 4,
+       .num_bulk_out = 4,
+       .num_ports = 4,
+#endif
+       .open = mos7840_open,
+       .close = mos7840_close,
+       .write = mos7840_write,
+       .write_room = mos7840_write_room,
+       .chars_in_buffer = mos7840_chars_in_buffer,
+       .throttle = mos7840_throttle,
+       .unthrottle = mos7840_unthrottle,
+       .calc_num_ports = mos7840_calc_num_ports,
+#ifdef MCSSerialProbe
+       .probe = mos7840_serial_probe,
+#endif
+       .ioctl = mos7840_ioctl,
+       .set_termios = mos7840_set_termios,
+       .break_ctl = mos7840_break,
+       .tiocmget = mos7840_tiocmget,
+       .tiocmset = mos7840_tiocmset,
+       .attach = mos7840_startup,
+       .shutdown = mos7840_shutdown,
+       .read_bulk_callback = mos7840_bulk_in_callback,
+       .read_int_callback = mos7840_interrupt_callback,
+};
+
+static struct usb_driver io_driver = {
+       .name = "mos7840",
+       .probe = usb_serial_probe,
+       .disconnect = usb_serial_disconnect,
+       .id_table = moschip_id_table_combined,
+};
+
+/****************************************************************************
+ * moschip7840_init
+ *     This is called by the module subsystem, or on startup to initialize us
+ ****************************************************************************/
+static int __init moschip7840_init(void)
+{
+       int retval;
+
+       dbg("%s \n", " mos7840_init :entering..........");
+
+       /* Register with the usb serial */
+       retval = usb_serial_register(&moschip7840_4port_device);
+
+       if (retval)
+               goto failed_port_device_register;
+
+       dbg("%s\n", "Entring...");
+       info(DRIVER_DESC " " DRIVER_VERSION);
+
+       /* Register with the usb */
+       retval = usb_register(&io_driver);
+
+       if (retval)
+               goto failed_usb_register;
+
+       if (retval == 0) {
+               dbg("%s\n", "Leaving...");
+               return 0;
+       }
+
+      failed_usb_register:
+       usb_serial_deregister(&moschip7840_4port_device);
+
+      failed_port_device_register:
+
+       return retval;
+}
+
+/****************************************************************************
+ * moschip7840_exit
+ *     Called when the driver is about to be unloaded.
+ ****************************************************************************/
+static void __exit moschip7840_exit(void)
+{
+
+       dbg("%s \n", " mos7840_exit :entering..........");
+
+       usb_deregister(&io_driver);
+
+       usb_serial_deregister(&moschip7840_4port_device);
+
+       dbg("%s\n", "Entring...");
+}
+
+module_init(moschip7840_init);
+module_exit(moschip7840_exit);
+
+/* Module information */
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
index 65e4d046951aa7439c0de36eda9b699a90b2a476..1036d436ed231116e7283ea94c59a056f1206e7d 100644 (file)
@@ -81,10 +81,11 @@ static struct usb_device_id id_table [] = {
        { USB_DEVICE(SPEEDDRAGON_VENDOR_ID, SPEEDDRAGON_PRODUCT_ID) },
        { USB_DEVICE(DATAPILOT_U2_VENDOR_ID, DATAPILOT_U2_PRODUCT_ID) },
        { USB_DEVICE(BELKIN_VENDOR_ID, BELKIN_PRODUCT_ID) },
+       { USB_DEVICE(ALCOR_VENDOR_ID, ALCOR_PRODUCT_ID) },
        { }                                     /* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+MODULE_DEVICE_TABLE(usb, id_table);
 
 static struct usb_driver pl2303_driver = {
        .name =         "pl2303",
@@ -127,65 +128,6 @@ static struct usb_driver pl2303_driver = {
 #define UART_OVERRUN_ERROR             0x40
 #define UART_CTS                       0x80
 
-/* function prototypes for a PL2303 serial converter */
-static int pl2303_open (struct usb_serial_port *port, struct file *filp);
-static void pl2303_close (struct usb_serial_port *port, struct file *filp);
-static void pl2303_set_termios (struct usb_serial_port *port,
-                               struct termios *old);
-static int pl2303_ioctl (struct usb_serial_port *port, struct file *file,
-                        unsigned int cmd, unsigned long arg);
-static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs);
-static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static int pl2303_write (struct usb_serial_port *port,
-                        const unsigned char *buf, int count);
-static void pl2303_send (struct usb_serial_port *port);
-static int pl2303_write_room(struct usb_serial_port *port);
-static int pl2303_chars_in_buffer(struct usb_serial_port *port);
-static void pl2303_break_ctl(struct usb_serial_port *port,int break_state);
-static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file);
-static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
-                           unsigned int set, unsigned int clear);
-static int pl2303_startup (struct usb_serial *serial);
-static void pl2303_shutdown (struct usb_serial *serial);
-static struct pl2303_buf *pl2303_buf_alloc(unsigned int size);
-static void pl2303_buf_free(struct pl2303_buf *pb);
-static void pl2303_buf_clear(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb);
-static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
-       unsigned int count);
-static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
-       unsigned int count);
-
-
-/* All of the device info needed for the PL2303 SIO serial converter */
-static struct usb_serial_driver pl2303_device = {
-       .driver = {
-               .owner =        THIS_MODULE,
-               .name =         "pl2303",
-       },
-       .id_table =             id_table,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          1,
-       .num_bulk_out =         1,
-       .num_ports =            1,
-       .open =                 pl2303_open,
-       .close =                pl2303_close,
-       .write =                pl2303_write,
-       .ioctl =                pl2303_ioctl,
-       .break_ctl =            pl2303_break_ctl,
-       .set_termios =          pl2303_set_termios,
-       .tiocmget =             pl2303_tiocmget,
-       .tiocmset =             pl2303_tiocmset,
-       .read_bulk_callback =   pl2303_read_bulk_callback,
-       .read_int_callback =    pl2303_read_int_callback,
-       .write_bulk_callback =  pl2303_write_bulk_callback,
-       .write_room =           pl2303_write_room,
-       .chars_in_buffer =      pl2303_chars_in_buffer,
-       .attach =               pl2303_startup,
-       .shutdown =             pl2303_shutdown,
-};
 
 enum pl2303_type {
        type_0,         /* don't know the difference between type 0 and */
@@ -204,8 +146,166 @@ struct pl2303_private {
        enum pl2303_type type;
 };
 
+/*
+ * pl2303_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
+{
+       struct pl2303_buf *pb;
+
+       if (size == 0)
+               return NULL;
+
+       pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
+       if (pb == NULL)
+               return NULL;
+
+       pb->buf_buf = kmalloc(size, GFP_KERNEL);
+       if (pb->buf_buf == NULL) {
+               kfree(pb);
+               return NULL;
+       }
+
+       pb->buf_size = size;
+       pb->buf_get = pb->buf_put = pb->buf_buf;
+
+       return pb;
+}
+
+/*
+ * pl2303_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+static void pl2303_buf_free(struct pl2303_buf *pb)
+{
+       if (pb) {
+               kfree(pb->buf_buf);
+               kfree(pb);
+       }
+}
+
+/*
+ * pl2303_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+static void pl2303_buf_clear(struct pl2303_buf *pb)
+{
+       if (pb != NULL)
+               pb->buf_get = pb->buf_put;
+               /* equivalent to a get of all data available */
+}
+
+/*
+ * pl2303_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
+{
+       if (pb == NULL)
+               return 0;
+
+       return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_space_avail
+ *
+ * Return the number of bytes of space available in the circular
+ * buffer.
+ */
+static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
+{
+       if (pb == NULL)
+               return 0;
+
+       return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
+}
+
+/*
+ * pl2303_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
+                                  unsigned int count)
+{
+       unsigned int len;
+
+       if (pb == NULL)
+               return 0;
+
+       len  = pl2303_buf_space_avail(pb);
+       if (count > len)
+               count = len;
+
+       if (count == 0)
+               return 0;
+
+       len = pb->buf_buf + pb->buf_size - pb->buf_put;
+       if (count > len) {
+               memcpy(pb->buf_put, buf, len);
+               memcpy(pb->buf_buf, buf+len, count - len);
+               pb->buf_put = pb->buf_buf + count - len;
+       } else {
+               memcpy(pb->buf_put, buf, count);
+               if (count < len)
+                       pb->buf_put += count;
+               else /* count == len */
+                       pb->buf_put = pb->buf_buf;
+       }
+
+       return count;
+}
+
+/*
+ * pl2303_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
+                                  unsigned int count)
+{
+       unsigned int len;
+
+       if (pb == NULL)
+               return 0;
+
+       len = pl2303_buf_data_avail(pb);
+       if (count > len)
+               count = len;
+
+       if (count == 0)
+               return 0;
+
+       len = pb->buf_buf + pb->buf_size - pb->buf_get;
+       if (count > len) {
+               memcpy(buf, pb->buf_get, len);
+               memcpy(buf+len, pb->buf_buf, count - len);
+               pb->buf_get = pb->buf_buf + count - len;
+       } else {
+               memcpy(buf, pb->buf_get, count);
+               if (count < len)
+                       pb->buf_get += count;
+               else /* count == len */
+                       pb->buf_get = pb->buf_buf;
+       }
+
+       return count;
+}
 
-static int pl2303_startup (struct usb_serial *serial)
+static int pl2303_startup(struct usb_serial *serial)
 {
        struct pl2303_private *priv;
        enum pl2303_type type = type_0;
@@ -247,36 +347,17 @@ cleanup:
        return -ENOMEM;
 }
 
-static int set_control_lines (struct usb_device *dev, u8 value)
+static int set_control_lines(struct usb_device *dev, u8 value)
 {
        int retval;
        
-       retval = usb_control_msg (dev, usb_sndctrlpipe (dev, 0),
-                                 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
-                                 value, 0, NULL, 0, 100);
+       retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                                SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
+                                value, 0, NULL, 0, 100);
        dbg("%s - value = %d, retval = %d", __FUNCTION__, value, retval);
        return retval;
 }
 
-static int pl2303_write (struct usb_serial_port *port,  const unsigned char *buf, int count)
-{
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
-
-       dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
-
-       if (!count)
-               return count;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       count = pl2303_buf_put(priv->buf, buf, count);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       pl2303_send(port);
-
-       return count;
-}
-
 static void pl2303_send(struct usb_serial_port *port)
 {
        int count, result;
@@ -293,7 +374,7 @@ static void pl2303_send(struct usb_serial_port *port)
        }
 
        count = pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer,
-               port->bulk_out_size);
+                              port->bulk_out_size);
 
        if (count == 0) {
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -304,13 +385,15 @@ static void pl2303_send(struct usb_serial_port *port)
 
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
+                             port->write_urb->transfer_buffer);
 
        port->write_urb->transfer_buffer_length = count;
        port->write_urb->dev = port->serial->dev;
-       result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
+       result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
        if (result) {
-               dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
+               dev_err(&port->dev, "%s - failed submitting write urb,"
+                       " error %d\n", __FUNCTION__, result);
                priv->write_urb_in_use = 0;
                // TODO: reschedule pl2303_send
        }
@@ -318,6 +401,26 @@ static void pl2303_send(struct usb_serial_port *port)
        usb_serial_port_softint(port);
 }
 
+static int pl2303_write(struct usb_serial_port *port, const unsigned char *buf,
+                       int count)
+{
+       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+
+       dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count);
+
+       if (!count)
+               return count;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       count = pl2303_buf_put(priv->buf, buf, count);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       pl2303_send(port);
+
+       return count;
+}
+
 static int pl2303_write_room(struct usb_serial_port *port)
 {
        struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -350,7 +453,8 @@ static int pl2303_chars_in_buffer(struct usb_serial_port *port)
        return chars;
 }
 
-static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+static void pl2303_set_termios(struct usb_serial_port *port,
+                              struct termios *old_termios)
 {
        struct usb_serial *serial = port->serial;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -371,7 +475,8 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
        spin_lock_irqsave(&priv->lock, flags);
        if (!priv->termios_initialized) {
                *(port->tty->termios) = tty_std_termios;
-               port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+               port->tty->termios->c_cflag = B9600 | CS8 | CREAD |
+                                             HUPCL | CLOCAL;
                priv->termios_initialized = 1;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -380,24 +485,24 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
        /* check that they really want us to change something */
        if (old_termios) {
                if ((cflag == old_termios->c_cflag) &&
-                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-                   dbg("%s - nothing to change...", __FUNCTION__);
-                   return;
+                   (RELEVANT_IFLAG(port->tty->termios->c_iflag) ==
+                    RELEVANT_IFLAG(old_termios->c_iflag))) {
+                       dbg("%s - nothing to change...", __FUNCTION__);
+                       return;
                }
        }
 
-       buf = kzalloc (7, GFP_KERNEL);
+       buf = kzalloc(7, GFP_KERNEL);
        if (!buf) {
                dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
                return;
        }
-       
-       i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0),
-                            GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
-                            0, 0, buf, 7, 100);
-       dbg ("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
-            buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
+       i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+                           GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
+                           0, 0, buf, 7, 100);
+       dbg("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
+           buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
        if (cflag & CSIZE) {
                switch (cflag & CSIZE) {
@@ -429,7 +534,8 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
                case B230400:   baud = 230400;  break;
                case B460800:   baud = 460800;  break;
                default:
-                       dev_err(&port->dev, "pl2303 driver does not support the baudrate requested (fix it)\n");
+                       dev_err(&port->dev, "pl2303 driver does not support"
+                               " the baudrate requested (fix it)\n");
                        break;
        }
        dbg("%s - baud = %d", __FUNCTION__, baud);
@@ -469,10 +575,10 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
                dbg("%s - parity = none", __FUNCTION__);
        }
 
-       i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
-                            SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE, 
-                            0, 0, buf, 7, 100);
-       dbg ("0x21:0x20:0:0  %d", i);
+       i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                           SET_LINE_REQUEST, SET_LINE_REQUEST_TYPE,
+                           0, 0, buf, 7, 100);
+       dbg("0x21:0x20:0:0  %d", i);
 
        /* change control lines if we are switching to or from B0 */
        spin_lock_irqsave(&priv->lock, flags);
@@ -488,13 +594,13 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
        } else {
                spin_unlock_irqrestore(&priv->lock, flags);
        }
-       
+
        buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
 
-       i = usb_control_msg (serial->dev, usb_rcvctrlpipe (serial->dev, 0),
-                            GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
-                            0, 0, buf, 7, 100);
-       dbg ("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
+       i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+                           GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
+                           0, 0, buf, 7, 100);
+       dbg("0xa1:0x21:0:0  %d - %x %x %x %x %x %x %x", i,
             buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
        if (cflag & CRTSCTS) {
@@ -503,18 +609,82 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
                        index = 0x61;
                else
                        index = 0x41;
-               i = usb_control_msg(serial->dev, 
+               i = usb_control_msg(serial->dev,
                                    usb_sndctrlpipe(serial->dev, 0),
                                    VENDOR_WRITE_REQUEST,
                                    VENDOR_WRITE_REQUEST_TYPE,
                                    0x0, index, NULL, 0, 100);
-               dbg ("0x40:0x1:0x0:0x%x  %d", index, i);
+               dbg("0x40:0x1:0x0:0x%x  %d", index, i);
        }
 
-       kfree (buf);
+       kfree(buf);
 }
 
-static int pl2303_open (struct usb_serial_port *port, struct file *filp)
+static void pl2303_close(struct usb_serial_port *port, struct file *filp)
+{
+       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       unsigned int c_cflag;
+       int bps;
+       long timeout;
+       wait_queue_t wait;
+
+       dbg("%s - port %d", __FUNCTION__, port->number);
+
+       /* wait for data to drain from the buffer */
+       spin_lock_irqsave(&priv->lock, flags);
+       timeout = PL2303_CLOSING_WAIT;
+       init_waitqueue_entry(&wait, current);
+       add_wait_queue(&port->tty->write_wait, &wait);
+       for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               if (pl2303_buf_data_avail(priv->buf) == 0 ||
+                   timeout == 0 || signal_pending(current) ||
+                   !usb_get_intfdata(port->serial->interface)) /* disconnect */
+                       break;
+               spin_unlock_irqrestore(&priv->lock, flags);
+               timeout = schedule_timeout(timeout);
+               spin_lock_irqsave(&priv->lock, flags);
+       }
+       set_current_state(TASK_RUNNING);
+       remove_wait_queue(&port->tty->write_wait, &wait);
+       /* clear out any remaining data in the buffer */
+       pl2303_buf_clear(priv->buf);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       /* wait for characters to drain from the device */
+       /* (this is long enough for the entire 256 byte */
+       /* pl2303 hardware buffer to drain with no flow */
+       /* control for data rates of 1200 bps or more, */
+       /* for lower rates we should really know how much */
+       /* data is in the buffer to compute a delay */
+       /* that is not unnecessarily long) */
+       bps = tty_get_baud_rate(port->tty);
+       if (bps > 1200)
+               timeout = max((HZ*2560)/bps,HZ/10);
+       else
+               timeout = 2*HZ;
+       schedule_timeout_interruptible(timeout);
+
+       /* shutdown our urbs */
+       dbg("%s - shutting down urbs", __FUNCTION__);
+       usb_kill_urb(port->write_urb);
+       usb_kill_urb(port->read_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       if (port->tty) {
+               c_cflag = port->tty->termios->c_cflag;
+               if (c_cflag & HUPCL) {
+                       /* drop DTR and RTS */
+                       spin_lock_irqsave(&priv->lock, flags);
+                       priv->line_control = 0;
+                       spin_unlock_irqrestore(&priv->lock, flags);
+                       set_control_lines(port->serial->dev, 0);
+               }
+       }
+}
+
+static int pl2303_open(struct usb_serial_port *port, struct file *filp)
 {
        struct termios tmp_termios;
        struct usb_serial *serial = port->serial;
@@ -566,100 +736,37 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
 
        kfree(buf);
 
-       /* Setup termios */
-       if (port->tty) {
-               pl2303_set_termios (port, &tmp_termios);
-       }
-
-       //FIXME: need to assert RTS and DTR if CRTSCTS off
-
-       dbg("%s - submitting read urb", __FUNCTION__);
-       port->read_urb->dev = serial->dev;
-       result = usb_submit_urb (port->read_urb, GFP_KERNEL);
-       if (result) {
-               dev_err(&port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
-               pl2303_close (port, NULL);
-               return -EPROTO;
-       }
-
-       dbg("%s - submitting interrupt urb", __FUNCTION__);
-       port->interrupt_in_urb->dev = serial->dev;
-       result = usb_submit_urb (port->interrupt_in_urb, GFP_KERNEL);
-       if (result) {
-               dev_err(&port->dev, "%s - failed submitting interrupt urb, error %d\n", __FUNCTION__, result);
-               pl2303_close (port, NULL);
-               return -EPROTO;
-       }
-       return 0;
-}
-
-
-static void pl2303_close (struct usb_serial_port *port, struct file *filp)
-{
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
-       unsigned int c_cflag;
-       int bps;
-       long timeout;
-       wait_queue_t wait;
-
-       dbg("%s - port %d", __FUNCTION__, port->number);
-
-       /* wait for data to drain from the buffer */
-       spin_lock_irqsave(&priv->lock, flags);
-       timeout = PL2303_CLOSING_WAIT;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&port->tty->write_wait, &wait);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (pl2303_buf_data_avail(priv->buf) == 0
-               || timeout == 0 || signal_pending(current)
-               || !usb_get_intfdata(port->serial->interface))  /* disconnect */
-                       break;
-               spin_unlock_irqrestore(&priv->lock, flags);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irqsave(&priv->lock, flags);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&port->tty->write_wait, &wait);
-       /* clear out any remaining data in the buffer */
-       pl2303_buf_clear(priv->buf);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* wait for characters to drain from the device */
-       /* (this is long enough for the entire 256 byte */
-       /* pl2303 hardware buffer to drain with no flow */
-       /* control for data rates of 1200 bps or more, */
-       /* for lower rates we should really know how much */
-       /* data is in the buffer to compute a delay */
-       /* that is not unnecessarily long) */
-       bps = tty_get_baud_rate(port->tty);
-       if (bps > 1200)
-               timeout = max((HZ*2560)/bps,HZ/10);
-       else
-               timeout = 2*HZ;
-       schedule_timeout_interruptible(timeout);
-
-       /* shutdown our urbs */
-       dbg("%s - shutting down urbs", __FUNCTION__);
-       usb_kill_urb(port->write_urb);
-       usb_kill_urb(port->read_urb);
-       usb_kill_urb(port->interrupt_in_urb);
-
+       /* Setup termios */
        if (port->tty) {
-               c_cflag = port->tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       /* drop DTR and RTS */
-                       spin_lock_irqsave(&priv->lock, flags);
-                       priv->line_control = 0;
-                       spin_unlock_irqrestore (&priv->lock, flags);
-                       set_control_lines (port->serial->dev, 0);
-               }
+               pl2303_set_termios(port, &tmp_termios);
+       }
+
+       //FIXME: need to assert RTS and DTR if CRTSCTS off
+
+       dbg("%s - submitting read urb", __FUNCTION__);
+       port->read_urb->dev = serial->dev;
+       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
+       if (result) {
+               dev_err(&port->dev, "%s - failed submitting read urb,"
+                       " error %d\n", __FUNCTION__, result);
+               pl2303_close(port, NULL);
+               return -EPROTO;
+       }
+
+       dbg("%s - submitting interrupt urb", __FUNCTION__);
+       port->interrupt_in_urb->dev = serial->dev;
+       result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+       if (result) {
+               dev_err(&port->dev, "%s - failed submitting interrupt urb,"
+                       " error %d\n", __FUNCTION__, result);
+               pl2303_close(port, NULL);
+               return -EPROTO;
        }
+       return 0;
 }
 
-static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
-                           unsigned int set, unsigned int clear)
+static int pl2303_tiocmset(struct usb_serial_port *port, struct file *file,
+                          unsigned int set, unsigned int clear)
 {
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
@@ -668,7 +775,7 @@ static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
        if (!usb_get_intfdata(port->serial->interface))
                return -ENODEV;
 
-       spin_lock_irqsave (&priv->lock, flags);
+       spin_lock_irqsave(&priv->lock, flags);
        if (set & TIOCM_RTS)
                priv->line_control |= CONTROL_RTS;
        if (set & TIOCM_DTR)
@@ -678,12 +785,12 @@ static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
        if (clear & TIOCM_DTR)
                priv->line_control &= ~CONTROL_DTR;
        control = priv->line_control;
-       spin_unlock_irqrestore (&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
-       return set_control_lines (port->serial->dev, control);
+       return set_control_lines(port->serial->dev, control);
 }
 
-static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file)
+static int pl2303_tiocmget(struct usb_serial_port *port, struct file *file)
 {
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
@@ -696,10 +803,10 @@ static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file)
        if (!usb_get_intfdata(port->serial->interface))
                return -ENODEV;
 
-       spin_lock_irqsave (&priv->lock, flags);
+       spin_lock_irqsave(&priv->lock, flags);
        mcr = priv->line_control;
        status = priv->line_status;
-       spin_unlock_irqrestore (&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        result = ((mcr & CONTROL_DTR)           ? TIOCM_DTR : 0)
                  | ((mcr & CONTROL_RTS)        ? TIOCM_RTS : 0)
@@ -721,22 +828,22 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        unsigned int status;
        unsigned int changed;
 
-       spin_lock_irqsave (&priv->lock, flags);
+       spin_lock_irqsave(&priv->lock, flags);
        prevstatus = priv->line_status;
-       spin_unlock_irqrestore (&priv->lock, flags);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        while (1) {
                interruptible_sleep_on(&priv->delta_msr_wait);
                /* see if a signal did it */
                if (signal_pending(current))
                        return -ERESTARTSYS;
-               
-               spin_lock_irqsave (&priv->lock, flags);
+
+               spin_lock_irqsave(&priv->lock, flags);
                status = priv->line_status;
-               spin_unlock_irqrestore (&priv->lock, flags);
-               
+               spin_unlock_irqrestore(&priv->lock, flags);
+
                changed=prevstatus^status;
-               
+
                if (((arg & TIOCM_RNG) && (changed & UART_RING)) ||
                    ((arg & TIOCM_DSR) && (changed & UART_DSR)) ||
                    ((arg & TIOCM_CD)  && (changed & UART_DCD)) ||
@@ -749,7 +856,8 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        return 0;
 }
 
-static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
+static int pl2303_ioctl(struct usb_serial_port *port, struct file *file,
+                       unsigned int cmd, unsigned long arg)
 {
        dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
 
@@ -766,7 +874,7 @@ static int pl2303_ioctl (struct usb_serial_port *port, struct file *file, unsign
        return -ENOIOCTLCMD;
 }
 
-static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
+static void pl2303_break_ctl(struct usb_serial_port *port, int break_state)
 {
        struct usb_serial *serial = port->serial;
        u16 state;
@@ -780,15 +888,14 @@ static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
                state = BREAK_ON;
        dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
 
-       result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
-                                 BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 
-                                 0, NULL, 0, 100);
+       result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                                BREAK_REQUEST, BREAK_REQUEST_TYPE, state,
+                                0, NULL, 0, 100);
        if (result)
                dbg("%s - error sending break = %d", __FUNCTION__, result);
 }
 
-
-static void pl2303_shutdown (struct usb_serial *serial)
+static void pl2303_shutdown(struct usb_serial *serial)
 {
        int i;
        struct pl2303_private *priv;
@@ -802,7 +909,7 @@ static void pl2303_shutdown (struct usb_serial *serial)
                        kfree(priv);
                        usb_set_serial_port_data(serial->port[i], NULL);
                }
-       }               
+       }
 }
 
 static void pl2303_update_line_status(struct usb_serial_port *port,
@@ -814,29 +921,33 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
        unsigned long flags;
        u8 status_idx = UART_STATE;
        u8 length = UART_STATE + 1;
+       u16 idv, idp;
+
+       idv = le16_to_cpu(port->serial->dev->descriptor.idVendor);
+       idp = le16_to_cpu(port->serial->dev->descriptor.idProduct);
 
-       if ((le16_to_cpu(port->serial->dev->descriptor.idVendor) == SIEMENS_VENDOR_ID) &&
-           (le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X65 ||
-            le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_SX1 ||
-            le16_to_cpu(port->serial->dev->descriptor.idProduct) == SIEMENS_PRODUCT_ID_X75)) {
-               length = 1;
-               status_idx = 0;
+
+       if (idv == SIEMENS_VENDOR_ID) {
+               if (idp == SIEMENS_PRODUCT_ID_X65 ||
+                   idp == SIEMENS_PRODUCT_ID_SX1 ||
+                   idp == SIEMENS_PRODUCT_ID_X75) {
+
+                       length = 1;
+                       status_idx = 0;
+               }
        }
 
        if (actual_length < length)
-               goto exit;
+               return;
 
         /* Save off the uart status for others to look at */
        spin_lock_irqsave(&priv->lock, flags);
        priv->line_status = data[status_idx];
        spin_unlock_irqrestore(&priv->lock, flags);
-       wake_up_interruptible (&priv->delta_msr_wait);
-
-exit:
-       return;
+       wake_up_interruptible(&priv->delta_msr_wait);
 }
 
-static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs)
+static void pl2303_read_int_callback(struct urb *urb, struct pt_regs *regs)
 {
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
        unsigned char *data = urb->transfer_buffer;
@@ -853,25 +964,29 @@ static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+                   urb->status);
                return;
        default:
-               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__,
+                   urb->status);
                goto exit;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+                             urb->actual_length, urb->transfer_buffer);
+
        pl2303_update_line_status(port, data, actual_length);
 
 exit:
-       status = usb_submit_urb (urb, GFP_ATOMIC);
+       status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status)
-               dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+               dev_err(&urb->dev->dev,
+                       "%s - usb_submit_urb failed with result %d\n",
                        __FUNCTION__, status);
 }
 
-
-static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void pl2303_read_bulk_callback(struct urb *urb, struct pt_regs *regs)
 {
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -892,20 +1007,25 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
                        return;
                }
                if (urb->status == -EPROTO) {
-                       /* PL2303 mysteriously fails with -EPROTO reschedule the read */
-                       dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);
+                       /* PL2303 mysteriously fails with -EPROTO reschedule
+                        * the read */
+                       dbg("%s - caught -EPROTO, resubmitting the urb",
+                           __FUNCTION__);
                        urb->status = 0;
                        urb->dev = port->serial->dev;
                        result = usb_submit_urb(urb, GFP_ATOMIC);
                        if (result)
-                               dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+                               dev_err(&urb->dev->dev, "%s - failed"
+                                       " resubmitting read urb, error %d\n",
+                                       __FUNCTION__, result);
                        return;
                }
                dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
                return;
        }
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+       usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+                             urb->actual_length, data);
 
        /* get tty_flag from status */
        tty_flag = TTY_NORMAL;
@@ -914,7 +1034,7 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
        status = priv->line_status;
        priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
        spin_unlock_irqrestore(&priv->lock, flags);
-       wake_up_interruptible (&priv->delta_msr_wait);
+       wake_up_interruptible(&priv->delta_msr_wait);
 
        /* break takes precedence over parity, */
        /* which takes precedence over framing errors */
@@ -933,8 +1053,8 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
                if (status & UART_OVERRUN_ERROR)
                        tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                for (i = 0; i < urb->actual_length; ++i)
-                       tty_insert_flip_char (tty, data[i], tty_flag);
-               tty_flip_buffer_push (tty);
+                       tty_insert_flip_char(tty, data[i], tty_flag);
+               tty_flip_buffer_push(tty);
        }
 
        /* Schedule the next read _if_ we are still open */
@@ -942,15 +1062,14 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
                urb->dev = port->serial->dev;
                result = usb_submit_urb(urb, GFP_ATOMIC);
                if (result)
-                       dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+                       dev_err(&urb->dev->dev, "%s - failed resubmitting"
+                               " read urb, error %d\n", __FUNCTION__, result);
        }
 
        return;
 }
 
-
-
-static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+static void pl2303_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
 {
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -966,18 +1085,21 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
        case -ENOENT:
        case -ESHUTDOWN:
                /* this urb is terminated, clean up */
-               dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+               dbg("%s - urb shutting down with status: %d", __FUNCTION__,
+                   urb->status);
                priv->write_urb_in_use = 0;
                return;
        default:
                /* error in the urb, so we have to resubmit it */
                dbg("%s - Overflow in write", __FUNCTION__);
-               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
+                   urb->status);
                port->write_urb->transfer_buffer_length = 1;
                port->write_urb->dev = port->serial->dev;
-               result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
+               result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
                if (result)
-                       dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", __FUNCTION__, result);
+                       dev_err(&urb->dev->dev, "%s - failed resubmitting write"
+                               " urb, error %d\n", __FUNCTION__, result);
                else
                        return;
        }
@@ -988,191 +1110,38 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
        pl2303_send(port);
 }
 
+/* All of the device info needed for the PL2303 SIO serial converter */
+static struct usb_serial_driver pl2303_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "pl2303",
+       },
+       .id_table =             id_table,
+       .num_interrupt_in =     NUM_DONT_CARE,
+       .num_bulk_in =          1,
+       .num_bulk_out =         1,
+       .num_ports =            1,
+       .open =                 pl2303_open,
+       .close =                pl2303_close,
+       .write =                pl2303_write,
+       .ioctl =                pl2303_ioctl,
+       .break_ctl =            pl2303_break_ctl,
+       .set_termios =          pl2303_set_termios,
+       .tiocmget =             pl2303_tiocmget,
+       .tiocmset =             pl2303_tiocmset,
+       .read_bulk_callback =   pl2303_read_bulk_callback,
+       .read_int_callback =    pl2303_read_int_callback,
+       .write_bulk_callback =  pl2303_write_bulk_callback,
+       .write_room =           pl2303_write_room,
+       .chars_in_buffer =      pl2303_chars_in_buffer,
+       .attach =               pl2303_startup,
+       .shutdown =             pl2303_shutdown,
+};
 
-/*
- * pl2303_buf_alloc
- *
- * Allocate a circular buffer and all associated memory.
- */
-
-static struct pl2303_buf *pl2303_buf_alloc(unsigned int size)
-{
-
-       struct pl2303_buf *pb;
-
-
-       if (size == 0)
-               return NULL;
-
-       pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL);
-       if (pb == NULL)
-               return NULL;
-
-       pb->buf_buf = kmalloc(size, GFP_KERNEL);
-       if (pb->buf_buf == NULL) {
-               kfree(pb);
-               return NULL;
-       }
-
-       pb->buf_size = size;
-       pb->buf_get = pb->buf_put = pb->buf_buf;
-
-       return pb;
-
-}
-
-
-/*
- * pl2303_buf_free
- *
- * Free the buffer and all associated memory.
- */
-
-static void pl2303_buf_free(struct pl2303_buf *pb)
-{
-       if (pb) {
-               kfree(pb->buf_buf);
-               kfree(pb);
-       }
-}
-
-
-/*
- * pl2303_buf_clear
- *
- * Clear out all data in the circular buffer.
- */
-
-static void pl2303_buf_clear(struct pl2303_buf *pb)
-{
-       if (pb != NULL)
-               pb->buf_get = pb->buf_put;
-               /* equivalent to a get of all data available */
-}
-
-
-/*
- * pl2303_buf_data_avail
- *
- * Return the number of bytes of data available in the circular
- * buffer.
- */
-
-static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb)
-{
-       if (pb != NULL)
-               return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size);
-       else
-               return 0;
-}
-
-
-/*
- * pl2303_buf_space_avail
- *
- * Return the number of bytes of space available in the circular
- * buffer.
- */
-
-static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb)
-{
-       if (pb != NULL)
-               return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size);
-       else
-               return 0;
-}
-
-
-/*
- * pl2303_buf_put
- *
- * Copy data data from a user buffer and put it into the circular buffer.
- * Restrict to the amount of space available.
- *
- * Return the number of bytes copied.
- */
-
-static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf,
-       unsigned int count)
-{
-
-       unsigned int len;
-
-
-       if (pb == NULL)
-               return 0;
-
-       len  = pl2303_buf_space_avail(pb);
-       if (count > len)
-               count = len;
-
-       if (count == 0)
-               return 0;
-
-       len = pb->buf_buf + pb->buf_size - pb->buf_put;
-       if (count > len) {
-               memcpy(pb->buf_put, buf, len);
-               memcpy(pb->buf_buf, buf+len, count - len);
-               pb->buf_put = pb->buf_buf + count - len;
-       } else {
-               memcpy(pb->buf_put, buf, count);
-               if (count < len)
-                       pb->buf_put += count;
-               else /* count == len */
-                       pb->buf_put = pb->buf_buf;
-       }
-
-       return count;
-
-}
-
-
-/*
- * pl2303_buf_get
- *
- * Get data from the circular buffer and copy to the given buffer.
- * Restrict to the amount of data available.
- *
- * Return the number of bytes copied.
- */
-
-static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf,
-       unsigned int count)
-{
-
-       unsigned int len;
-
-
-       if (pb == NULL)
-               return 0;
-
-       len = pl2303_buf_data_avail(pb);
-       if (count > len)
-               count = len;
-
-       if (count == 0)
-               return 0;
-
-       len = pb->buf_buf + pb->buf_size - pb->buf_get;
-       if (count > len) {
-               memcpy(buf, pb->buf_get, len);
-               memcpy(buf+len, pb->buf_buf, count - len);
-               pb->buf_get = pb->buf_buf + count - len;
-       } else {
-               memcpy(buf, pb->buf_get, count);
-               if (count < len)
-                       pb->buf_get += count;
-               else /* count == len */
-                       pb->buf_get = pb->buf_buf;
-       }
-
-       return count;
-
-}
-
-static int __init pl2303_init (void)
+static int __init pl2303_init(void)
 {
        int retval;
+
        retval = usb_serial_register(&pl2303_device);
        if (retval)
                goto failed_usb_serial_register;
@@ -1187,14 +1156,12 @@ failed_usb_serial_register:
        return retval;
 }
 
-
-static void __exit pl2303_exit (void)
+static void __exit pl2303_exit(void)
 {
-       usb_deregister (&pl2303_driver);
-       usb_serial_deregister (&pl2303_device);
+       usb_deregister(&pl2303_driver);
+       usb_serial_deregister(&pl2303_device);
 }
 
-
 module_init(pl2303_init);
 module_exit(pl2303_exit);
 
index 55195e76eb6fb1bf42af33c07be1953e7048a64c..762cc290ef5869df049629c196b4e59f2f845926 100644 (file)
@@ -89,3 +89,7 @@
 /* Belkin "F5U257" Serial Adapter */
 #define BELKIN_VENDOR_ID       0x050d
 #define BELKIN_PRODUCT_ID      0x0257
+
+/* Alcor Micro Corp. USB 2.0 TO RS-232 */
+#define ALCOR_VENDOR_ID                0x058F
+#define ALCOR_PRODUCT_ID       0x9720
index e06a41bd0f3ba4b458aaf11470c901965cff7710..0222d92842b8ba79e89404d58ebcd06c729e8a2a 100644 (file)
@@ -676,33 +676,29 @@ int usb_serial_probe(struct usb_interface *interface,
        iface_desc = interface->cur_altsetting;
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;
-               
-               if ((endpoint->bEndpointAddress & 0x80) &&
-                   ((endpoint->bmAttributes & 3) == 0x02)) {
+
+               if (usb_endpoint_is_bulk_in(endpoint)) {
                        /* we found a bulk in endpoint */
                        dbg("found bulk in on endpoint %d", i);
                        bulk_in_endpoint[num_bulk_in] = endpoint;
                        ++num_bulk_in;
                }
 
-               if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-                   ((endpoint->bmAttributes & 3) == 0x02)) {
+               if (usb_endpoint_is_bulk_out(endpoint)) {
                        /* we found a bulk out endpoint */
                        dbg("found bulk out on endpoint %d", i);
                        bulk_out_endpoint[num_bulk_out] = endpoint;
                        ++num_bulk_out;
                }
-               
-               if ((endpoint->bEndpointAddress & 0x80) &&
-                   ((endpoint->bmAttributes & 3) == 0x03)) {
+
+               if (usb_endpoint_is_int_in(endpoint)) {
                        /* we found a interrupt in endpoint */
                        dbg("found interrupt in on endpoint %d", i);
                        interrupt_in_endpoint[num_interrupt_in] = endpoint;
                        ++num_interrupt_in;
                }
 
-               if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-                   ((endpoint->bmAttributes & 3) == 0x03)) {
+               if (usb_endpoint_is_int_out(endpoint)) {
                        /* we found an interrupt out endpoint */
                        dbg("found interrupt out on endpoint %d", i);
                        interrupt_out_endpoint[num_interrupt_out] = endpoint;
@@ -716,14 +712,15 @@ int usb_serial_probe(struct usb_interface *interface,
        if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
             (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
            ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
-            (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID))) {
+            (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID)) ||
+           ((le16_to_cpu(dev->descriptor.idVendor) == ALCOR_VENDOR_ID) &&
+            (le16_to_cpu(dev->descriptor.idProduct) == ALCOR_PRODUCT_ID))) {
                if (interface != dev->actconfig->interface[0]) {
                        /* check out the endpoints of the other interface*/
                        iface_desc = dev->actconfig->interface[0]->cur_altsetting;
                        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                                endpoint = &iface_desc->endpoint[i].desc;
-                               if ((endpoint->bEndpointAddress & 0x80) &&
-                                   ((endpoint->bmAttributes & 3) == 0x03)) {
+                               if (usb_endpoint_is_int_in(endpoint)) {
                                        /* we found a interrupt in endpoint */
                                        dbg("found interrupt in for Prolific device on separate interface");
                                        interrupt_in_endpoint[num_interrupt_in] = endpoint;
@@ -937,7 +934,10 @@ int usb_serial_probe(struct usb_interface *interface,
 
                snprintf (&port->dev.bus_id[0], sizeof(port->dev.bus_id), "ttyUSB%d", port->number);
                dbg ("%s - registering %s", __FUNCTION__, port->dev.bus_id);
-               device_register (&port->dev);
+               retval = device_register(&port->dev);
+               if (retval)
+                       dev_err(&port->dev, "Error registering port device, "
+                               "continuing\n");
        }
 
        usb_serial_console_init (debug, minor);
index be9eec2257436c2152aecd9e0d20462f69902b2e..86e48c42d6af3cf955c2cb4320bb33eeda29f77e 100644 (file)
@@ -135,6 +135,18 @@ config USB_STORAGE_ONETOUCH
          this input in any keybinding software. (e.g. gnome's keyboard short-
          cuts)
 
+config USB_STORAGE_KARMA
+       bool "Support for Rio Karma music player"
+       depends on USB_STORAGE
+       help
+         Say Y here to include additional code to support the Rio Karma
+         USB interface.
+
+         This code places the Rio Karma into mass storage mode, enabling
+         it to be mounted as an ordinary filesystem. Performing an eject
+         on the resulting scsi device node returns the Karma to normal
+         operation.
+
 config USB_LIBUSUAL
        bool "The shared table of common (or usual) storage devices"
        depends on USB
index 8cbba22508a47d77d3a39897d4138e7be5a7f7ae..023969b4385b689265b3836cb130a6dd8de64fad 100644 (file)
@@ -20,6 +20,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA)   += alauda.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA)    += karma.o
 
 usb-storage-objs :=    scsiglue.o protocol.o transport.o usb.o \
                        initializers.o $(usb-storage-obj-y)
index ab173b30076eb1b7ac2ec3a2fe257a78863918d5..5b06f9240d05caa2b348c7cf55cf520ff2ca2240 100644 (file)
 #include "debug.h"
 #include "transport.h"
 
-#define RIO_MSC 0x08
-#define RIOP_INIT "RIOP\x00\x01\x08"
-#define RIOP_INIT_LEN 7
-#define RIO_SEND_LEN 40
-#define RIO_RECV_LEN 0x200
-
 /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
  * mode */
 int usb_stor_euscsi_init(struct us_data *us)
@@ -97,70 +91,3 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
 
        return (res ? -1 : 0);
 }
-
-/* Place the Rio Karma into mass storage mode.
- *
- * The initialization begins by sending 40 bytes starting
- * RIOP\x00\x01\x08\x00, which the device will ack with a 512-byte
- * packet with the high four bits set and everything else null.
- *
- * Next, we send RIOP\x80\x00\x08\x00.  Each time, a 512 byte response
- * must be read, but we must loop until byte 5 in the response is 0x08,
- * indicating success.  */
-int rio_karma_init(struct us_data *us)
-{
-       int result, partial;
-       char *recv;
-       unsigned long timeout;
-
-       // us->iobuf is big enough to hold cmd but not receive
-       if (!(recv = kmalloc(RIO_RECV_LEN, GFP_KERNEL)))
-               goto die_nomem;
-
-       US_DEBUGP("Initializing Karma...\n");
-
-       memset(us->iobuf, 0, RIO_SEND_LEN);
-       memcpy(us->iobuf, RIOP_INIT, RIOP_INIT_LEN);
-
-       result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-               us->iobuf, RIO_SEND_LEN, &partial);
-       if (result != USB_STOR_XFER_GOOD)
-               goto die;
-
-       result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-               recv, RIO_RECV_LEN, &partial);
-       if (result != USB_STOR_XFER_GOOD)
-               goto die;
-
-       us->iobuf[4] = 0x80;
-       us->iobuf[5] = 0;
-       timeout = jiffies + msecs_to_jiffies(3000);
-       for (;;) {
-               US_DEBUGP("Sending init command\n");
-               result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-                       us->iobuf, RIO_SEND_LEN, &partial);
-               if (result != USB_STOR_XFER_GOOD)
-                       goto die;
-
-               result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-                       recv, RIO_RECV_LEN, &partial);
-               if (result != USB_STOR_XFER_GOOD)
-                       goto die;
-
-               if (recv[5] == RIO_MSC)
-                       break;
-               if (time_after(jiffies, timeout))
-                       goto die;
-               msleep(10);
-       }
-       US_DEBUGP("Karma initialized.\n");
-       kfree(recv);
-       return 0;
-
-die:
-       kfree(recv);
-die_nomem:
-       US_DEBUGP("Could not initialize karma.\n");
-       return USB_STOR_TRANSPORT_FAILED;
-}
-
index 927f7781080f0afebff4b1e5ee4602cf27b6526a..e2967a4d48a2e30d0fa694f233d10941ec88121a 100644 (file)
@@ -47,4 +47,3 @@ int usb_stor_euscsi_init(struct us_data *us);
 /* This function is required to activate all four slots on the UCR-61S2B
  * flash reader */
 int usb_stor_ucr61s2b_init(struct us_data *us);
-int rio_karma_init(struct us_data *us);
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
new file mode 100644 (file)
index 0000000..0d79ae5
--- /dev/null
@@ -0,0 +1,155 @@
+/* Driver for Rio Karma
+ *
+ *   (c) 2006 Bob Copeland <me@bobcopeland.com>
+ *   (c) 2006 Keith Bennett <keith@mcs.st-and.ac.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, 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 <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
+#include "usb.h"
+#include "transport.h"
+#include "debug.h"
+#include "karma.h"
+
+#define RIO_PREFIX "RIOP\x00"
+#define RIO_PREFIX_LEN 5
+#define RIO_SEND_LEN 40
+#define RIO_RECV_LEN 0x200
+
+#define RIO_ENTER_STORAGE 0x1
+#define RIO_LEAVE_STORAGE 0x2
+#define RIO_RESET 0xC
+
+extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data *);
+
+struct karma_data {
+       int in_storage;
+       char *recv;
+};
+
+/*
+ * Send commands to Rio Karma.
+ *
+ * For each command we send 40 bytes starting 'RIOP\0' followed by
+ * the command number and a sequence number, which the device will ack
+ * with a 512-byte packet with the high four bits set and everything
+ * else null.  Then we send 'RIOP\x80' followed by a zero and the
+ * sequence number, until byte 5 in the response repeats the sequence
+ * number.
+ */
+static int rio_karma_send_command(char cmd, struct us_data *us)
+{
+       int result, partial;
+       unsigned long timeout;
+       static unsigned char seq = 1;
+       struct karma_data *data = (struct karma_data *) us->extra;
+
+       US_DEBUGP("karma: sending command %04x\n", cmd);
+       memset(us->iobuf, 0, RIO_SEND_LEN);
+       memcpy(us->iobuf, RIO_PREFIX, RIO_PREFIX_LEN);
+       us->iobuf[5] = cmd;
+       us->iobuf[6] = seq;
+
+       timeout = jiffies + msecs_to_jiffies(6000);
+       for (;;) {
+               result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
+                       us->iobuf, RIO_SEND_LEN, &partial);
+               if (result != USB_STOR_XFER_GOOD)
+                       goto err;
+
+               result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
+                       data->recv, RIO_RECV_LEN, &partial);
+               if (result != USB_STOR_XFER_GOOD)
+                       goto err;
+
+               if (data->recv[5] == seq)
+                       break;
+
+               if (time_after(jiffies, timeout))
+                       goto err;
+
+               us->iobuf[4] = 0x80;
+               us->iobuf[5] = 0;
+               msleep(50);
+       }
+
+       seq++;
+       if (seq == 0)
+               seq = 1;
+
+       US_DEBUGP("karma: sent command %04x\n", cmd);
+       return 0;
+err:
+       US_DEBUGP("karma: command %04x failed\n", cmd);
+       return USB_STOR_TRANSPORT_FAILED;
+}
+
+/*
+ * Trap START_STOP and READ_10 to leave/re-enter storage mode.
+ * Everything else is propagated to the normal bulk layer.
+ */
+int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+       int ret;
+       struct karma_data *data = (struct karma_data *) us->extra;
+
+       if (srb->cmnd[0] == READ_10 && !data->in_storage) {
+               ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
+               if (ret)
+                       return ret;
+
+               data->in_storage = 1;
+               return usb_stor_Bulk_transport(srb, us);
+       } else if (srb->cmnd[0] == START_STOP) {
+               ret = rio_karma_send_command(RIO_LEAVE_STORAGE, us);
+               if (ret)
+                       return ret;
+
+               data->in_storage = 0;
+               return rio_karma_send_command(RIO_RESET, us);
+       }
+       return usb_stor_Bulk_transport(srb, us);
+}
+
+static void rio_karma_destructor(void *extra)
+{
+       struct karma_data *data = (struct karma_data *) extra;
+       kfree(data->recv);
+}
+
+int rio_karma_init(struct us_data *us)
+{
+       int ret = 0;
+       struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO);
+       if (!data)
+               goto out;
+
+       data->recv = kmalloc(RIO_RECV_LEN, GFP_NOIO);
+       if (!data->recv) {
+               kfree(data);
+               goto out;
+       }
+
+       us->extra = data;
+       us->extra_destructor = rio_karma_destructor;
+       ret = rio_karma_send_command(RIO_ENTER_STORAGE, us);
+       data->in_storage = (ret == 0);
+out:
+       return ret;
+}
diff --git a/drivers/usb/storage/karma.h b/drivers/usb/storage/karma.h
new file mode 100644 (file)
index 0000000..8a60972
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _KARMA_USB_H
+#define _KARMA_USB_H
+
+extern int rio_karma_init(struct us_data *us);
+extern int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us);
+
+#endif
index b1ec4a718547316c62cf39fa4872ffd7651424f9..599ad10a761b703da02f989eb51a88d0941ae0fd 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/usb.h>
 #include <linux/usb_usual.h>
 #include <linux/vmalloc.h>
+#include <linux/kthread.h>
 
 /*
  */
@@ -117,7 +118,7 @@ static int usu_probe(struct usb_interface *intf,
                         const struct usb_device_id *id)
 {
        unsigned long type;
-       int rc;
+       struct task_struct* task;
        unsigned long flags;
 
        type = USB_US_TYPE(id->driver_info);
@@ -132,8 +133,9 @@ static int usu_probe(struct usb_interface *intf,
        stat[type].fls |= USU_MOD_FL_THREAD;
        spin_unlock_irqrestore(&usu_lock, flags);
 
-       rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM);
-       if (rc < 0) {
+       task = kthread_run(usu_probe_thread, (void*)type, "libusual_%d", type);
+       if (IS_ERR(task)) {
+               int rc = PTR_ERR(task);
                printk(KERN_WARNING "libusual: "
                    "Unable to start the thread for %s: %d\n",
                    bias_names[type], rc);
@@ -175,8 +177,6 @@ static int usu_probe_thread(void *arg)
        int rc;
        unsigned long flags;
 
-       daemonize("libusual_%d", type); /* "usb-storage" is kinda too long */
-
        /* A completion does not work here because it's counted. */
        down(&usu_init_notify);
        up(&usu_init_notify);
index 313920d980c9aa7b7fc39c7864409b2ed7bb6130..f843a0bcf107a55b2d3f65a65be2875519357fc9 100644 (file)
@@ -135,6 +135,7 @@ int onetouch_connect_input(struct us_data *ss)
        struct usb_onetouch *onetouch;
        struct input_dev *input_dev;
        int pipe, maxp;
+       int error = -ENOMEM;
 
        interface = ss->pusb_intf->cur_altsetting;
 
@@ -211,15 +212,18 @@ int onetouch_connect_input(struct us_data *ss)
        ss->suspend_resume_hook = usb_onetouch_pm_hook;
 #endif
 
-       input_register_device(onetouch->dev);
+       error = input_register_device(onetouch->dev);
+       if (error)
+               goto fail3;
 
        return 0;
 
+ fail3:        usb_free_urb(onetouch->irq);
  fail2:        usb_buffer_free(udev, ONETOUCH_PKT_LEN,
                        onetouch->data, onetouch->data_dma);
  fail1:        kfree(onetouch);
        input_free_device(input_dev);
-       return -ENOMEM;
+       return error;
 }
 
 void onetouch_release_input(void *onetouch_)
index a4b7df9ff8c165fd3067f7c8e8ff5ead4becf2a4..e1072d52d6419a93b7b9135dd05cf5a09cb9b913 100644 (file)
@@ -72,12 +72,27 @@ static const char* host_info(struct Scsi_Host *host)
 
 static int slave_alloc (struct scsi_device *sdev)
 {
+       struct us_data *us = host_to_us(sdev->host);
+
        /*
         * Set the INQUIRY transfer length to 36.  We don't use any of
         * the extra data and many devices choke if asked for more or
         * less than 36 bytes.
         */
        sdev->inquiry_len = 36;
+
+       /*
+        * The UFI spec treates the Peripheral Qualifier bits in an
+        * INQUIRY result as reserved and requires devices to set them
+        * to 0.  However the SCSI spec requires these bits to be set
+        * to 3 to indicate when a LUN is not present.
+        *
+        * Let the scanning code know if this target merely sets
+        * Peripheral Device Type to 0x1f to indicate no LUN.
+        */
+       if (us->subclass == US_SC_UFI)
+               sdev->sdev_target->pdt_1f_for_no_lun = 1;
+
        return 0;
 }
 
index d6acc92a4ae36ac66757450f9522f7cb667128f6..f23514c4e649bdd6947ce0301cf730e2344ef540 100644 (file)
@@ -294,11 +294,6 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
                        return USB_STOR_XFER_ERROR;
                return USB_STOR_XFER_STALLED;
 
-       /* timeout or excessively long NAK */
-       case -ETIMEDOUT:
-               US_DEBUGP("-- timeout or NAK\n");
-               return USB_STOR_XFER_ERROR;
-
        /* babble - the device tried to send more than we wanted to read */
        case -EOVERFLOW:
                US_DEBUGP("-- babble\n");
index b130e170b4a8a44c94e6ed07844fcab01b326797..40bf159f7d5469b3440b9988a5ab50da1ff13447 100644 (file)
@@ -218,10 +218,12 @@ UNUSUAL_DEV(  0x0457, 0x0151, 0x0100, 0x0100,
                 US_SC_DEVICE, US_PR_DEVICE, NULL,
                 US_FL_NOT_LOCKABLE ),
 
+#ifdef CONFIG_USB_STORAGE_KARMA
 UNUSUAL_DEV(  0x045a, 0x5210, 0x0101, 0x0101,
                "Rio",
                "Rio Karma",
-               US_SC_SCSI, US_PR_BULK, rio_karma_init, 0),
+               US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0),
+#endif
 
 /* Patch submitted by Philipp Friedrich <philipp@void.at> */
 UNUSUAL_DEV(  0x0482, 0x0100, 0x0100, 0x0100,
@@ -631,6 +633,13 @@ UNUSUAL_DEV(  0x0595, 0x4343, 0x0000, 0x2210,
                "Digital Camera EX-20 DSC",
                US_SC_8070, US_PR_DEVICE, NULL, 0 ),
 
+/* Reported by <Hendryk.Pfeiffer@gmx.de> */
+UNUSUAL_DEV(  0x059f, 0x0643, 0x0000, 0x0000,
+               "LaCie",
+               "DVD+-RW",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_GO_SLOW ),
+
 /* Submitted by Joel Bourquard <numlock@freesurf.ch>
  * Some versions of this device need the SubClass and Protocol overrides
  * while others don't.
@@ -1254,6 +1263,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> */
+UNUSUAL_DEV(  0x0fce, 0xe030, 0x0000, 0x0000,
+               "Sony Ericsson",
+               "P990i",
+               US_SC_DEVICE, US_PR_DEVICE, NULL,
+               US_FL_FIX_CAPACITY ),
+
 /* Reported by Emmanuel Vasilakis <evas@forthnet.gr> */
 UNUSUAL_DEV(  0x0fce, 0xe031, 0x0000, 0x0000,
                "Sony Ericsson",
index 8d7bdcb5924d402f891cbf1a07c2584400a28cb3..b8d6031b09750245ce4bdece07ed7528e4a7e6c1 100644 (file)
@@ -98,6 +98,9 @@
 #ifdef CONFIG_USB_STORAGE_ALAUDA
 #include "alauda.h"
 #endif
+#ifdef CONFIG_USB_STORAGE_KARMA
+#include "karma.h"
+#endif
 
 /* Some informational data */
 MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
@@ -646,6 +649,14 @@ static int get_transport(struct us_data *us)
                break;
 #endif
 
+#ifdef CONFIG_USB_STORAGE_KARMA
+       case US_PR_KARMA:
+               us->transport_name = "Rio Karma/Bulk";
+               us->transport = rio_karma_transport;
+               us->transport_reset = usb_stor_Bulk_reset;
+               break;
+#endif
+
        default:
                return -EIO;
        }
index b362039792b30fb596a916f8229f00b536b368ef..1b51d3187a95c8d99c87de153de5afed4a9831ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * USB Skeleton driver - 2.0
+ * USB Skeleton driver - 2.2
  *
  * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
  *
@@ -7,9 +7,8 @@
  *     modify it under the terms of the GNU General Public License as
  *     published by the Free Software Foundation, version 2.
  *
- * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c 
- * but has been rewritten to be easy to read and use, as no locks are now
- * needed anymore.
+ * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c
+ * but has been rewritten to be easier to read and use.
  *
  */
 
@@ -21,6 +20,7 @@
 #include <linux/kref.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
+#include <linux/mutex.h>
 
 
 /* Define these values to match your devices */
@@ -32,38 +32,39 @@ static struct usb_device_id skel_table [] = {
        { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
        { }                                     /* Terminating entry */
 };
-MODULE_DEVICE_TABLE (usb, skel_table);
+MODULE_DEVICE_TABLE(usb, skel_table);
 
 
 /* Get a minor range for your devices from the usb maintainer */
 #define USB_SKEL_MINOR_BASE    192
 
 /* our private defines. if this grows any larger, use your own .h file */
-#define MAX_TRANSFER           ( PAGE_SIZE - 512 )
+#define MAX_TRANSFER           (PAGE_SIZE - 512)
 #define WRITES_IN_FLIGHT       8
 
 /* Structure to hold all of our device specific stuff */
 struct usb_skel {
-       struct usb_device *     udev;                   /* the usb device for this device */
-       struct usb_interface *  interface;              /* the interface for this device */
+       struct usb_device       *dev;                   /* the usb device for this device */
+       struct usb_interface    *interface;             /* the interface for this device */
        struct semaphore        limit_sem;              /* limiting the number of writes in progress */
-       unsigned char *         bulk_in_buffer;         /* the buffer to receive data */
+       unsigned char           *bulk_in_buffer;        /* the buffer to receive data */
        size_t                  bulk_in_size;           /* the size of the receive buffer */
        __u8                    bulk_in_endpointAddr;   /* the address of the bulk in endpoint */
        __u8                    bulk_out_endpointAddr;  /* the address of the bulk out endpoint */
        struct kref             kref;
+       struct mutex            io_mutex;               /* synchronize I/O with disconnect */
 };
 #define to_skel_dev(d) container_of(d, struct usb_skel, kref)
 
 static struct usb_driver skel_driver;
 
 static void skel_delete(struct kref *kref)
-{      
+{
        struct usb_skel *dev = to_skel_dev(kref);
 
        usb_put_dev(dev->udev);
-       kfree (dev->bulk_in_buffer);
-       kfree (dev);
+       kfree(dev->bulk_in_buffer);
+       kfree(dev);
 }
 
 static int skel_open(struct inode *inode, struct file *file)
@@ -89,6 +90,11 @@ static int skel_open(struct inode *inode, struct file *file)
                goto exit;
        }
 
+       /* prevent the device from being autosuspended */
+       retval = usb_autopm_get_interface(interface);
+       if (retval)
+               goto exit;
+
        /* increment our usage count for the device */
        kref_get(&dev->kref);
 
@@ -107,6 +113,12 @@ static int skel_release(struct inode *inode, struct file *file)
        if (dev == NULL)
                return -ENODEV;
 
+       /* allow the device to be autosuspended */
+       mutex_lock(&dev->io_mutex);
+       if (dev->interface)
+               usb_autopm_put_interface(dev->interface);
+       mutex_unlock(&dev->io_mutex);
+
        /* decrement the count on our device */
        kref_put(&dev->kref, skel_delete);
        return 0;
@@ -115,11 +127,17 @@ static int skel_release(struct inode *inode, struct file *file)
 static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
        struct usb_skel *dev;
-       int retval = 0;
+       int retval;
        int bytes_read;
 
        dev = (struct usb_skel *)file->private_data;
-       
+
+       mutex_lock(&dev->io_mutex);
+       if (!dev->interface) {          /* disconnect() was called */
+               retval = -ENODEV;
+               goto exit;
+       }
+
        /* do a blocking bulk read to get data from the device */
        retval = usb_bulk_msg(dev->udev,
                              usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
@@ -135,6 +153,8 @@ static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *
                        retval = bytes_read;
        }
 
+exit:
+       mutex_unlock(&dev->io_mutex);
        return retval;
 }
 
@@ -145,16 +165,16 @@ static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
        dev = (struct usb_skel *)urb->context;
 
        /* sync/async unlink faults aren't errors */
-       if (urb->status && 
-           !(urb->status == -ENOENT || 
+       if (urb->status &&
+           !(urb->status == -ENOENT ||
              urb->status == -ECONNRESET ||
              urb->status == -ESHUTDOWN)) {
-               dbg("%s - nonzero write bulk status received: %d",
+               err("%s - nonzero write bulk status received: %d",
                    __FUNCTION__, urb->status);
        }
 
        /* free up our allocated buffer */
-       usb_buffer_free(urb->dev, urb->transfer_buffer_length, 
+       usb_buffer_free(urb->dev, urb->transfer_buffer_length,
                        urb->transfer_buffer, urb->transfer_dma);
        up(&dev->limit_sem);
 }
@@ -179,6 +199,12 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
                goto exit;
        }
 
+       mutex_lock(&dev->io_mutex);
+       if (!dev->interface) {          /* disconnect() was called */
+               retval = -ENODEV;
+               goto error;
+       }
+
        /* create a urb, and a buffer for it, and copy the data to the urb */
        urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!urb) {
@@ -213,17 +239,22 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou
        /* release our reference to this urb, the USB core will eventually free it entirely */
        usb_free_urb(urb);
 
-exit:
+       mutex_unlock(&dev->io_mutex);
        return writesize;
 
 error:
-       usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
-       usb_free_urb(urb);
+       if (urb) {
+               usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma);
+               usb_free_urb(urb);
+       }
+       mutex_unlock(&dev->io_mutex);
        up(&dev->limit_sem);
+
+exit:
        return retval;
 }
 
-static struct file_operations skel_fops = {
+static const struct file_operations skel_fops = {
        .owner =        THIS_MODULE,
        .read =         skel_read,
        .write =        skel_write,
@@ -231,7 +262,7 @@ static struct file_operations skel_fops = {
        .release =      skel_release,
 };
 
-/* 
+/*
  * usb class driver info in order to get a minor number from the usb core,
  * and to have the device registered with the driver core
  */
@@ -243,7 +274,7 @@ static struct usb_class_driver skel_class = {
 
 static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id)
 {
-       struct usb_skel *dev = NULL;
+       struct usb_skel *dev;
        struct usb_host_interface *iface_desc;
        struct usb_endpoint_descriptor *endpoint;
        size_t buffer_size;
@@ -252,12 +283,13 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
 
        /* allocate memory for our device state and initialize it */
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (dev == NULL) {
+       if (!dev) {
                err("Out of memory");
                goto error;
        }
        kref_init(&dev->kref);
        sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
+       mutex_init(&dev->io_mutex);
 
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
        dev->interface = interface;
@@ -269,10 +301,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
                endpoint = &iface_desc->endpoint[i].desc;
 
                if (!dev->bulk_in_endpointAddr &&
-                   ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-                                       == USB_DIR_IN) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                                       == USB_ENDPOINT_XFER_BULK)) {
+                   usb_endpoint_is_bulk_in(endpoint)) {
                        /* we found a bulk in endpoint */
                        buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
                        dev->bulk_in_size = buffer_size;
@@ -285,10 +314,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
                }
 
                if (!dev->bulk_out_endpointAddr &&
-                   ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-                                       == USB_DIR_OUT) &&
-                   ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-                                       == USB_ENDPOINT_XFER_BULK)) {
+                   usb_endpoint_is_bulk_out(endpoint)) {
                        /* we found a bulk out endpoint */
                        dev->bulk_out_endpointAddr = endpoint->bEndpointAddress;
                }
@@ -334,6 +360,11 @@ static void skel_disconnect(struct usb_interface *interface)
        /* give back our minor */
        usb_deregister_dev(interface, &skel_class);
 
+       /* prevent more I/O from starting */
+       mutex_lock(&dev->io_mutex);
+       dev->interface = NULL;
+       mutex_unlock(&dev->io_mutex);
+
        unlock_kernel();
 
        /* decrement our usage count */
@@ -367,7 +398,7 @@ static void __exit usb_skel_exit(void)
        usb_deregister(&skel_driver);
 }
 
-module_init (usb_skel_init);
-module_exit (usb_skel_exit);
+module_init(usb_skel_init);
+module_exit(usb_skel_exit);
 
 MODULE_LICENSE("GPL");
index e308ed2d249abdbebda6a00422206b2708b8d6f4..365de5dcc888edf9c37766276f091ae689da648e 100644 (file)
@@ -2621,25 +2621,28 @@ static int radeon_restore_pci_cfg(struct radeonfb_info *rinfo)
 }
 
 
-int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
         struct fb_info *info = pci_get_drvdata(pdev);
         struct radeonfb_info *rinfo = info->par;
        int i;
 
-       if (state.event == pdev->dev.power.power_state.event)
+       if (mesg.event == pdev->dev.power.power_state.event)
                return 0;
 
-       printk(KERN_DEBUG "radeonfb (%s): suspending to state: %d...\n",
-              pci_name(pdev), state.event);
+       printk(KERN_DEBUG "radeonfb (%s): suspending for event: %d...\n",
+              pci_name(pdev), mesg.event);
 
        /* For suspend-to-disk, we cheat here. We don't suspend anything and
         * let fbcon continue drawing until we are all set. That shouldn't
         * really cause any problem at this point, provided that the wakeup
         * code knows that any state in memory may not match the HW
         */
-       if (state.event == PM_EVENT_FREEZE)
+       switch (mesg.event) {
+       case PM_EVENT_FREEZE:           /* about to take snapshot */
+       case PM_EVENT_PRETHAW:          /* before restoring snapshot */
                goto done;
+       }
 
        acquire_console_sem();
 
@@ -2706,7 +2709,7 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t state)
        release_console_sem();
 
  done:
-       pdev->dev.power.power_state = state;
+       pdev->dev.power.power_state = mesg;
 
        return 0;
 }
index ffc72ae3ada80a01f98c959099b004e57bc5aed4..fe1488374f620cad6fa5fce1e8eef17b3ff79132 100644 (file)
@@ -20,7 +20,7 @@
 
 #include <asm/cpu/dac.h>
 #include <asm/hp6xx/hp6xx.h>
-#include <asm/hd64461/hd64461.h>
+#include <asm/hd64461.h>
 
 #define HP680_MAX_INTENSITY 255
 #define HP680_DEFAULT_INTENSITY 10
@@ -163,6 +163,6 @@ static void __exit hp680bl_exit(void)
 module_init(hp680bl_init);
 module_exit(hp680bl_exit);
 
-MODULE_AUTHOR("Andriy Skulysh <askulysh@image.kiev.ua>");
+MODULE_AUTHOR("Andriy Skulysh <askulysh@gmail.com>");
 MODULE_DESCRIPTION("HP Jornada 680 Backlight Driver");
 MODULE_LICENSE("GPL");
index 4444bef68fbafb03ca4d41aae1a46a8abfd740e6..aa3935df852ad6f9f04f1fce4c53091c8f0f8511 100644 (file)
@@ -6,7 +6,7 @@ menu "Console display driver support"
 
 config VGA_CONSOLE
        bool "VGA text console" if EMBEDDED || !X86
-       depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE
+       depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE && !SUPERH
        default y
        help
          Saying Y here will allow you to use Linux in text mode through a
index 4cc6b454265ee8b7ccdd60d439856365bc1ab867..3afb472763c0488fddcd1dd5a4c0e3bb5817c1f8 100644 (file)
@@ -4,7 +4,7 @@
  * (C) 1999 Mihai Spatar
  * (C) 2000 YAEGASHI Takeshi
  * (C) 2003, 2004 Paul Mundt
- * (C) 2003, 2004 Andriy Skulysh
+ * (C) 2003, 2004, 2006 Andriy Skulysh
  *
  *  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
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/fb.h>
 
 #include <asm/machvec.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
-#include <asm/hd64461/hd64461.h>
-
-#ifdef MACH_HP600
+#include <asm/hd64461.h>
 #include <asm/cpu/dac.h>
 #include <asm/hp6xx/hp6xx.h>
-#endif
 
 #define        WIDTH 640
 
@@ -45,7 +43,6 @@ static struct fb_var_screeninfo hitfb_var __initdata = {
 static struct fb_fix_screeninfo hitfb_fix __initdata = {
        .id             = "Hitachi HD64461",
        .type           = FB_TYPE_PACKED_PIXELS,
-       .ypanstep       = 8,
        .accel          = FB_ACCEL_NONE,
 };
 
@@ -73,26 +70,14 @@ static inline void hitfb_accel_set_dest(int truecolor, u16 dx, u16 dy,
        if (truecolor)
                saddr <<= 1;
 
-       fb_writew(width, HD64461_BBTDWR);
-       fb_writew(height, HD64461_BBTDHR);
+       fb_writew(width-1, HD64461_BBTDWR);
+       fb_writew(height-1, HD64461_BBTDHR);
 
        fb_writew(saddr & 0xffff, HD64461_BBTDSARL);
        fb_writew(saddr >> 16, HD64461_BBTDSARH);
 
 }
 
-static inline void hitfb_accel_solidfill(int truecolor, u16 dx, u16 dy,
-                                        u16 width, u16 height, u16 color)
-{
-       hitfb_accel_set_dest(truecolor, dx, dy, width, height);
-
-       fb_writew(0x00f0, HD64461_BBTROPR);
-       fb_writew(16, HD64461_BBTMDR);
-       fb_writew(color, HD64461_GRSCR);
-
-       hitfb_accel_start(truecolor);
-}
-
 static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx,
                                      u16 dy, u16 width, u16 height, u16 rop,
                                      u32 mask_addr)
@@ -100,6 +85,8 @@ static inline void hitfb_accel_bitblt(int truecolor, u16 sx, u16 sy, u16 dx,
        u32 saddr, daddr;
        u32 maddr = 0;
 
+       height--;
+       width--;
        fb_writew(rop, HD64461_BBTROPR);
        if ((sy < dy) || ((sy == dy) && (sx <= dx))) {
                saddr = WIDTH * (sy + height) + sx + width;
@@ -146,6 +133,7 @@ static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
        if (rect->rop != ROP_COPY)
                cfb_fillrect(p, rect);
        else {
+               hitfb_accel_wait();
                fb_writew(0x00f0, HD64461_BBTROPR);
                fb_writew(16, HD64461_BBTMDR);
 
@@ -161,16 +149,15 @@ static void hitfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
                                             rect->height);
                        hitfb_accel_start(0);
                }
-               hitfb_accel_wait();
        }
 }
 
 static void hitfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
 {
+       hitfb_accel_wait();
        hitfb_accel_bitblt(p->var.bits_per_pixel == 16, area->sx, area->sy,
                           area->dx, area->dy, area->width, area->height,
                           0x00cc, 0);
-       hitfb_accel_wait();
 }
 
 static int hitfb_pan_display(struct fb_var_screeninfo *var,
@@ -182,7 +169,7 @@ static int hitfb_pan_display(struct fb_var_screeninfo *var,
        if (xoffset != 0)
                return -EINVAL;
 
-       fb_writew(yoffset, HD64461_LCDCBAR);
+       fb_writew((yoffset*info->fix.line_length)>>10, HD64461_LCDCBAR);
 
        return 0;
 }
@@ -192,12 +179,6 @@ int hitfb_blank(int blank_mode, struct fb_info *info)
        unsigned short v;
 
        if (blank_mode) {
-#ifdef MACH_HP600
-               sh_dac_disable(DAC_LCD_BRIGHTNESS);
-               v = fb_readw(HD64461_GPBDR);
-               v |= HD64461_GPBDR_LCDOFF;
-               fb_writew(v, HD64461_GPBDR);
-#endif
                v = fb_readw(HD64461_LDR1);
                v &= ~HD64461_LDR1_DON;
                fb_writew(v, HD64461_LDR1);
@@ -213,19 +194,18 @@ int hitfb_blank(int blank_mode, struct fb_info *info)
                v = fb_readw(HD64461_STBCR);
                v &= ~HD64461_STBCR_SLCDST;
                fb_writew(v, HD64461_STBCR);
-#ifdef MACH_HP600
-               sh_dac_enable(DAC_LCD_BRIGHTNESS);
-               v = fb_readw(HD64461_GPBDR);
-               v &= ~HD64461_GPBDR_LCDOFF;
-               fb_writew(v, HD64461_GPBDR);
-#endif
-               v = fb_readw(HD64461_LDR1);
-               v |= HD64461_LDR1_DON;
-               fb_writew(v, HD64461_LDR1);
 
                v = fb_readw(HD64461_LCDCCR);
-               v &= ~HD64461_LCDCCR_MOFF;
+               v &= ~(HD64461_LCDCCR_MOFF | HD64461_LCDCCR_STREQ);
                fb_writew(v, HD64461_LCDCCR);
+
+               do {
+                   v = fb_readw(HD64461_LCDCCR);
+               } while(v&HD64461_LCDCCR_STBACK);
+
+               v = fb_readw(HD64461_LDR1);
+               v |= HD64461_LDR1_DON;
+               fb_writew(v, HD64461_LDR1);
        }
        return 0;
 }
@@ -233,7 +213,7 @@ int hitfb_blank(int blank_mode, struct fb_info *info)
 static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                           unsigned blue, unsigned transp, struct fb_info *info)
 {
-       if (regno >= info->cmap.len)
+       if (regno >= 256)
                return 1;
 
        switch (info->var.bits_per_pixel) {
@@ -244,6 +224,8 @@ static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
                fb_writew(blue >> 10, HD64461_CPTWDR);
                break;
        case 16:
+               if (regno >= 16)
+                       return 1;
                ((u32 *) (info->pseudo_palette))[regno] =
                    ((red & 0xf800)) |
                    ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11);
@@ -252,26 +234,113 @@ static int hitfb_setcolreg(unsigned regno, unsigned red, unsigned green,
        return 0;
 }
 
+static int hitfb_sync(struct fb_info *info)
+{
+       hitfb_accel_wait();
+
+       return 0;
+}
+
+static int hitfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+       int maxy;
+
+       var->xres = info->var.xres;
+       var->xres_virtual = info->var.xres;
+       var->yres = info->var.yres;
+
+       if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16))
+               var->bits_per_pixel = info->var.bits_per_pixel;
+
+       if (var->yres_virtual < var->yres)
+               var->yres_virtual = var->yres;
+
+       maxy = info->fix.smem_len / var->xres;
+
+       if (var->bits_per_pixel == 16)
+               maxy /= 2;
+
+       if (var->yres_virtual > maxy)
+               var->yres_virtual = maxy;
+
+       var->xoffset = 0;
+       var->yoffset = 0;
+
+       switch (var->bits_per_pixel) {
+       case 8:
+               var->red.offset = 0;
+               var->red.length = 8;
+               var->green.offset = 0;
+               var->green.length = 8;
+               var->blue.offset = 0;
+               var->blue.length = 8;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               break;
+       case 16:                /* RGB 565 */
+               var->red.offset = 11;
+               var->red.length = 5;
+               var->green.offset = 5;
+               var->green.length = 6;
+               var->blue.offset = 0;
+               var->blue.length = 5;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               break;
+       }
+
+       return 0;
+}
+
+static int hitfb_set_par(struct fb_info *info)
+{
+       unsigned short ldr3;
+
+       switch (info->var.bits_per_pixel) {
+       case 8:
+               info->fix.line_length = info->var.xres;
+               info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+               info->fix.ypanstep = 16;
+               break;
+       case 16:
+               info->fix.line_length = info->var.xres*2;
+               info->fix.visual = FB_VISUAL_TRUECOLOR;
+               info->fix.ypanstep = 8;
+               break;
+       }
+
+       fb_writew(info->fix.line_length, HD64461_LCDCLOR);
+       ldr3 = fb_readw(HD64461_LDR3);
+       ldr3 &= ~15;
+       ldr3 |= (info->var.bits_per_pixel == 8) ? 4 : 8;
+       fb_writew(ldr3, HD64461_LDR3);
+       return 0;
+}
+
 static struct fb_ops hitfb_ops = {
        .owner          = THIS_MODULE,
+       .fb_check_var   = hitfb_check_var,
+       .fb_set_par             = hitfb_set_par,
        .fb_setcolreg   = hitfb_setcolreg,
        .fb_blank       = hitfb_blank,
+       .fb_sync        = hitfb_sync,
        .fb_pan_display = hitfb_pan_display,
        .fb_fillrect    = hitfb_fillrect,
        .fb_copyarea    = hitfb_copyarea,
        .fb_imageblit   = cfb_imageblit,
 };
 
-int __init hitfb_init(void)
+static int __init hitfb_probe(struct platform_device *dev)
 {
        unsigned short lcdclor, ldr3, ldvndr;
-       int size;
 
        if (fb_get_options("hitfb", NULL))
                return -ENODEV;
 
+       hitfb_fix.mmio_start = CONFIG_HD64461_IOBASE+0x1000;
+       hitfb_fix.mmio_len = 0x1000;
        hitfb_fix.smem_start = CONFIG_HD64461_IOBASE + 0x02000000;
-       hitfb_fix.smem_len = (MACH_HP690) ? 1024 * 1024 : 512 * 1024;
+       hitfb_fix.smem_len = 512 * 1024;
 
        lcdclor = fb_readw(HD64461_LCDCLOR);
        ldvndr = fb_readw(HD64461_LDVNDR);
@@ -321,12 +390,12 @@ int __init hitfb_init(void)
        fb_info.var = hitfb_var;
        fb_info.fix = hitfb_fix;
        fb_info.pseudo_palette = pseudo_palette;
-       fb_info.flags = FBINFO_DEFAULT;
+       fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
+               FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_COPYAREA;
 
        fb_info.screen_base = (void *)hitfb_fix.smem_start;
 
-       size = (fb_info.var.bits_per_pixel == 8) ? 256 : 16;
-       fb_alloc_cmap(&fb_info.cmap, size, 0);
+       fb_alloc_cmap(&fb_info.cmap, 256, 0);
 
        if (register_framebuffer(&fb_info) < 0)
                return -EINVAL;
@@ -336,9 +405,75 @@ int __init hitfb_init(void)
        return 0;
 }
 
+static int __devexit hitfb_remove(struct platform_device *dev)
+{
+       return unregister_framebuffer(&fb_info);
+}
+
+#ifdef CONFIG_PM
+static int hitfb_suspend(struct platform_device *dev, pm_message_t state)
+{
+       u16 v;
+
+       hitfb_blank(1,0);
+       v = fb_readw(HD64461_STBCR);
+       v |= HD64461_STBCR_SLCKE_IST;
+       fb_writew(v, HD64461_STBCR);
+
+       return 0;
+}
+
+static int hitfb_resume(struct platform_device *dev)
+{
+       u16 v;
+
+       v = fb_readw(HD64461_STBCR);
+       v &= ~HD64461_STBCR_SLCKE_OST;
+       msleep(100);
+       v = fb_readw(HD64461_STBCR);
+       v &= ~HD64461_STBCR_SLCKE_IST;
+       fb_writew(v, HD64461_STBCR);
+       hitfb_blank(0,0);
+
+       return 0;
+}
+#endif
+
+static struct platform_driver hitfb_driver = {
+       .probe          = hitfb_probe,
+       .remove         = __devexit_p(hitfb_remove),
+#ifdef CONFIG_PM
+       .suspend        = hitfb_suspend,
+       .resume         = hitfb_resume,
+#endif
+       .driver         = {
+               .name   = "hitfb",
+       },
+};
+
+static struct platform_device hitfb_device = {
+       .name   = "hitfb",
+       .id     = -1,
+};
+
+static int __init hitfb_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&hitfb_driver);
+       if (!ret) {
+               ret = platform_device_register(&hitfb_device);
+               if (ret)
+                       platform_driver_unregister(&hitfb_driver);
+       }
+       return ret;
+}
+
+
 static void __exit hitfb_exit(void)
 {
-       unregister_framebuffer(&fb_info);
+       platform_device_unregister(&hitfb_device);
+       platform_driver_unregister(&hitfb_driver);
 }
 
 module_init(hitfb_init);
index c1f7b49975dd1a8bb78fd1817ddfd33cd3e5018a..7d06b38e80a00f7e4f5d7ead2062a46da7e5730d 100644 (file)
@@ -98,7 +98,6 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name)
        chan->algo.getsda               = i810i2c_getsda;
        chan->algo.getscl               = i810i2c_getscl;
        chan->algo.udelay               = 10;
-       chan->algo.mdelay               = 10;
         chan->algo.timeout              = (HZ/2);
         chan->algo.data                 = chan;
 
index a6ca02f2156a810b03cc91161e1aba4644a7531e..d42edaccb84c732bab17286ef9b5fc90687ca419 100644 (file)
@@ -1554,15 +1554,17 @@ static struct fb_ops i810fb_ops __devinitdata = {
 /***********************************************************************
  *                         Power Management                            *
  ***********************************************************************/
-static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
+static int i810fb_suspend(struct pci_dev *dev, pm_message_t mesg)
 {
        struct fb_info *info = pci_get_drvdata(dev);
        struct i810fb_par *par = info->par;
 
-       par->cur_state = state.event;
+       par->cur_state = mesg.event;
 
-       if (state.event == PM_EVENT_FREEZE) {
-               dev->dev.power.power_state = state;
+       switch (mesg.event) {
+       case PM_EVENT_FREEZE:
+       case PM_EVENT_PRETHAW:
+               dev->dev.power.power_state = mesg;
                return 0;
        }
 
@@ -1578,7 +1580,7 @@ static int i810fb_suspend(struct pci_dev *dev, pm_message_t state)
 
        pci_save_state(dev);
        pci_disable_device(dev);
-       pci_set_power_state(dev, pci_choose_state(dev, state));
+       pci_set_power_state(dev, pci_choose_state(dev, mesg));
        release_console_sem();
 
        return 0;
index 57abbae5520f1d8cddb8fd93255c7eb7e706b23a..795c1a99a680b9f64d3ff84023b811291930b9bc 100644 (file)
@@ -95,12 +95,12 @@ static struct i2c_adapter matrox_i2c_adapter_template =
 
 static struct i2c_algo_bit_data matrox_i2c_algo_template =
 {
-       NULL,
-       matroxfb_gpio_setsda,
-       matroxfb_gpio_setscl,
-       matroxfb_gpio_getsda,
-       matroxfb_gpio_getscl,
-       10, 10, 100,
+       .setsda         = matroxfb_gpio_setsda,
+       .setscl         = matroxfb_gpio_setscl,
+       .getsda         = matroxfb_gpio_getsda,
+       .getscl         = matroxfb_gpio_getscl,
+       .udelay         = 10,
+       .timeout        = 100,
 };
 
 static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, 
index d4f850117874899f76afd661c5340fa2508d997f..f8cd4c519aebf1125ba9e6a347be3cdc67f80418 100644 (file)
@@ -950,24 +950,25 @@ static struct fb_ops nvidia_fb_ops = {
 };
 
 #ifdef CONFIG_PM
-static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t state)
+static int nvidiafb_suspend(struct pci_dev *dev, pm_message_t mesg)
 {
        struct fb_info *info = pci_get_drvdata(dev);
        struct nvidia_par *par = info->par;
 
+       if (mesg.event == PM_EVENT_PRETHAW)
+               mesg.event = PM_EVENT_FREEZE;
        acquire_console_sem();
-       par->pm_state = state.event;
+       par->pm_state = mesg.event;
 
-       if (state.event == PM_EVENT_FREEZE) {
-               dev->dev.power.power_state = state;
-       } else {
+       if (mesg.event == PM_EVENT_SUSPEND) {
                fb_set_suspend(info, 1);
                nvidiafb_blank(FB_BLANK_POWERDOWN, info);
                nvidia_write_regs(par, &par->SavedReg);
                pci_save_state(dev);
                pci_disable_device(dev);
-               pci_set_power_state(dev, pci_choose_state(dev, state));
+               pci_set_power_state(dev, pci_choose_state(dev, mesg));
        }
+       dev->dev.power.power_state = mesg;
 
        release_console_sem();
        return 0;
index 940ba2be55e9eddc0abd875320bfcc25ee5bdeb3..78dc59a1751bfcf43a9f96952959d09b20643070 100644 (file)
@@ -187,7 +187,7 @@ static short do_blank = 0;          /* (Un)Blank the screen */
 static unsigned int is_blanked = 0;            /* Is the screen blanked? */
 
 #ifdef CONFIG_SH_STORE_QUEUES
-static struct sq_mapping *pvr2fb_map;
+static unsigned long pvr2fb_map;
 #endif
 
 #ifdef CONFIG_SH_DMA
@@ -213,15 +213,17 @@ static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp);
 static int pvr2_init_cable(void);
 static int pvr2_get_param(const struct pvr2_params *p, const char *s,
                             int val, int size);
+#ifdef CONFIG_SH_DMA
 static ssize_t pvr2fb_write(struct file *file, const char *buf,
                            size_t count, loff_t *ppos);
+#endif
 
 static struct fb_ops pvr2fb_ops = {
-       .owner          = THIS_MODULE,
-       .fb_setcolreg   = pvr2fb_setcolreg,
-       .fb_blank       = pvr2fb_blank,
-       .fb_check_var   = pvr2fb_check_var,
-       .fb_set_par     = pvr2fb_set_par,
+       .owner          = THIS_MODULE,
+       .fb_setcolreg   = pvr2fb_setcolreg,
+       .fb_blank       = pvr2fb_blank,
+       .fb_check_var   = pvr2fb_check_var,
+       .fb_set_par     = pvr2fb_set_par,
 #ifdef CONFIG_SH_DMA
        .fb_write       = pvr2fb_write,
 #endif
@@ -783,7 +785,7 @@ static int __init pvr2fb_common_init(void)
                goto out_err;
        }
 
-       fb_memset((unsigned long)fb_info->screen_base, 0, pvr2_fix.smem_len);
+       fb_memset(fb_info->screen_base, 0, pvr2_fix.smem_len);
 
        pvr2_fix.ypanstep       = nopan  ? 0 : 1;
        pvr2_fix.ywrapstep      = nowrap ? 0 : 1;
@@ -820,7 +822,7 @@ static int __init pvr2fb_common_init(void)
               modememused >> 10, (unsigned long)(fb_info->fix.smem_len >> 10));
        printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", 
               fb_info->node, fb_info->var.xres, fb_info->var.yres,
-              fb_info->var.bits_per_pixel, 
+              fb_info->var.bits_per_pixel,
               get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel),
               (char *)pvr2_get_param(cables, NULL, cable_type, 3),
               (char *)pvr2_get_param(outputs, NULL, video_output, 3));
@@ -829,10 +831,10 @@ static int __init pvr2fb_common_init(void)
        printk(KERN_NOTICE "fb%d: registering with SQ API\n", fb_info->node);
 
        pvr2fb_map = sq_remap(fb_info->fix.smem_start, fb_info->fix.smem_len,
-                             fb_info->fix.id);
+                             fb_info->fix.id, pgprot_val(PAGE_SHARED));
 
        printk(KERN_NOTICE "fb%d: Mapped video memory to SQ addr 0x%lx\n",
-              fb_info->node, pvr2fb_map->sq_addr);
+              fb_info->node, pvr2fb_map);
 #endif
 
        return 0;
index e83befd16d634328ddb6029df79aaa3330f1a5a1..d7d810dbf0bdb6b1db553b35529eb99a651a2a25 100644 (file)
@@ -148,7 +148,6 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
                chan->adapter.algo_data         = &chan->algo;
                chan->adapter.dev.parent        = &chan->par->pcidev->dev;
                chan->algo.udelay               = 40;
-               chan->algo.mdelay               = 5;
                chan->algo.timeout              = 20;
                chan->algo.data                 = chan;
 
index 461e094e7b45de0a15829310a45e78163b66956b..82b3deaae02de532ba7ee3e34f21e47392d5a585 100644 (file)
@@ -2323,24 +2323,24 @@ static void __devexit savagefb_remove(struct pci_dev *dev)
        }
 }
 
-static int savagefb_suspend(struct pci_dev* dev, pm_message_t state)
+static int savagefb_suspend(struct pci_dev *dev, pm_message_t mesg)
 {
        struct fb_info *info = pci_get_drvdata(dev);
        struct savagefb_par *par = info->par;
 
        DBG("savagefb_suspend");
 
-
-       par->pm_state = state.event;
+       if (mesg.event == PM_EVENT_PRETHAW)
+               mesg.event = PM_EVENT_FREEZE;
+       par->pm_state = mesg.event;
+       dev->dev.power.power_state = mesg;
 
        /*
         * For PM_EVENT_FREEZE, do not power down so the console
         * can remain active.
         */
-       if (state.event == PM_EVENT_FREEZE) {
-               dev->dev.power.power_state = state;
+       if (mesg.event == PM_EVENT_FREEZE)
                return 0;
-       }
 
        acquire_console_sem();
        fb_set_suspend(info, 1);
@@ -2353,7 +2353,7 @@ static int savagefb_suspend(struct pci_dev* dev, pm_message_t state)
        savage_disable_mmio(par);
        pci_save_state(dev);
        pci_disable_device(dev);
-       pci_set_power_state(dev, pci_choose_state(dev, state));
+       pci_set_power_state(dev, pci_choose_state(dev, mesg));
        release_console_sem();
 
        return 0;
index eae50c9d6dc41f0ca06524357008775a59d74fe1..7a7ec2d1d2f4a8f60bb79c2f82bc0f110f9509b9 100644 (file)
@@ -204,7 +204,6 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode)
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = sb->s_blocksize;
                inode->i_blocks = 0;
                inode->i_rdev = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -950,9 +949,8 @@ v9fs_stat2inode(struct v9fs_stat *stat, struct inode *inode,
 
        inode->i_size = stat->length;
 
-       inode->i_blksize = sb->s_blocksize;
        inode->i_blocks =
-           (inode->i_size + inode->i_blksize - 1) >> sb->s_blocksize_bits;
+           (inode->i_size + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
 }
 
 /**
index a27002668bd36a7abb3074bfa41036ae16580b73..d311198bba439d812421331e7aea06a5046aa176 100644 (file)
@@ -826,6 +826,25 @@ config PROC_VMCORE
         help
         Exports the dump image of crashed kernel in ELF format.
 
+config PROC_SYSCTL
+       bool "Sysctl support (/proc/sys)" if EMBEDDED
+       depends on PROC_FS
+       select SYSCTL
+       default y
+       ---help---
+         The sysctl interface provides a means of dynamically changing
+         certain kernel parameters and variables on the fly without requiring
+         a recompile of the kernel or reboot of the system.  The primary
+         interface is through /proc/sys.  If you say Y here a tree of
+         modifiable sysctl entries will be generated beneath the
+          /proc/sys directory. They are explained in the files
+         in <file:Documentation/sysctl/>.  Note that enabling this
+         option will enlarge the kernel by at least 8 KB.
+
+         As it is generally a good thing, you should say Y here unless
+         building a kernel for install/rescue disks or your system is very
+         limited in memory.
+
 config SYSFS
        bool "sysfs file system support" if EMBEDDED
        default y
index 534f3eecc985c7b5bfe9231bd4807db4091e388d..7e7a04be1278cf36994a0c2f934419e2ba919060 100644 (file)
@@ -269,7 +269,6 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
        inode->i_ino     = obj->file_id;
        inode->i_size    = obj->size;
        inode->i_nlink   = 2;
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks  = (inode->i_size + sb->s_blocksize - 1) >>
                            sb->s_blocksize_bits;
 
index 82011019494ccf6bbcefa838e28b5c130739470b..9ade139086fcebb7c48206a686ac06011edea40c 100644 (file)
@@ -251,8 +251,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(adfs_inode_cachep))
-               printk(KERN_INFO "adfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(adfs_inode_cachep);
 }
 
 static struct super_operations adfs_sops = {
@@ -339,11 +338,10 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_flags |= MS_NODIRATIME;
 
-       asb = kmalloc(sizeof(*asb), GFP_KERNEL);
+       asb = kzalloc(sizeof(*asb), GFP_KERNEL);
        if (!asb)
                return -ENOMEM;
        sb->s_fs_info = asb;
-       memset(asb, 0, sizeof(*asb));
 
        /* set default options */
        asb->s_uid = 0;
index 17352011ab6700120d22501cc0ebce6992ba79dc..5ea72c3a16c3b52d4654d9a65223a09b6c87cbb4 100644 (file)
@@ -109,8 +109,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(affs_inode_cachep))
-               printk(KERN_INFO "affs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(affs_inode_cachep);
 }
 
 static struct super_operations affs_sops = {
@@ -280,11 +279,10 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_op                = &affs_sops;
        sb->s_flags |= MS_NODIRATIME;
 
-       sbi = kmalloc(sizeof(struct affs_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct affs_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(*sbi));
        init_MUTEX(&sbi->s_bmlock);
 
        if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
index 4ebb30a50ed5a876d28c7830e0083c10a1aa26f9..6f37754906c201cb49940b2efbd57b5c6b9a978f 100644 (file)
@@ -72,7 +72,6 @@ static int afs_inode_map_status(struct afs_vnode *vnode)
        inode->i_ctime.tv_sec   = vnode->status.mtime_server;
        inode->i_ctime.tv_nsec  = 0;
        inode->i_atime          = inode->i_mtime = inode->i_ctime;
-       inode->i_blksize        = PAGE_CACHE_SIZE;
        inode->i_blocks         = 0;
        inode->i_version        = vnode->fid.unique;
        inode->i_mapping->a_ops = &afs_fs_aops;
index 331f730a1fb34435223c000ea590ecd078a0784d..782ee7c600caf0ec80c43f9c91407d1d93d6d506 100644 (file)
@@ -281,11 +281,10 @@ int afs_vlocation_lookup(struct afs_cell *cell,
        spin_unlock(&cell->vl_gylock);
 
        /* not in the cell's in-memory lists - create a new record */
-       vlocation = kmalloc(sizeof(struct afs_vlocation), GFP_KERNEL);
+       vlocation = kzalloc(sizeof(struct afs_vlocation), GFP_KERNEL);
        if (!vlocation)
                return -ENOMEM;
 
-       memset(vlocation, 0, sizeof(struct afs_vlocation));
        atomic_set(&vlocation->usage, 1);
        INIT_LIST_HEAD(&vlocation->link);
        rwlock_init(&vlocation->lock);
index 0ff4b86476e39288313fe3f92bd7ed1aaaedd3d3..768c6dbd323ac625277d478086a98f4585a6ae88 100644 (file)
@@ -186,11 +186,10 @@ int afs_volume_lookup(const char *name, struct afs_cell *cell, int rwpath,
        _debug("creating new volume record");
 
        ret = -ENOMEM;
-       volume = kmalloc(sizeof(struct afs_volume), GFP_KERNEL);
+       volume = kzalloc(sizeof(struct afs_volume), GFP_KERNEL);
        if (!volume)
                goto error_up;
 
-       memset(volume, 0, sizeof(struct afs_volume));
        atomic_set(&volume->usage, 1);
        volume->type            = type;
        volume->type_force      = force;
index af2efbbb5d76ef7a6db921ba43316b5570c4dadf..2c9759baad61bf0f875c4adbb4abba6e8fdebb04 100644 (file)
@@ -129,10 +129,9 @@ int autofs_fill_super(struct super_block *s, void *data, int silent)
        struct autofs_sb_info *sbi;
        int minproto, maxproto;
 
-       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if ( !sbi )
                goto fail_unlock;
-       memset(sbi, 0, sizeof(*sbi));
        DPRINTK(("autofs: starting up, sbi = %p\n",sbi));
 
        s->s_fs_info = sbi;
@@ -217,7 +216,6 @@ static void autofs_read_inode(struct inode *inode)
        inode->i_nlink = 2;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        inode->i_blocks = 0;
-       inode->i_blksize = 1024;
 
        if ( ino == AUTOFS_ROOT_INO ) {
                inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
@@ -242,7 +240,7 @@ static void autofs_read_inode(struct inode *inode)
                
                inode->i_op = &autofs_symlink_inode_operations;
                sl = &sbi->symlink[n];
-               inode->u.generic_ip = sl;
+               inode->i_private = sl;
                inode->i_mode = S_IFLNK | S_IRWXUGO;
                inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = sl->mtime;
                inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
index 52e8772b066e33fece33d73ae5ddf30568c5b4ca..c74f2eb6577521ffec6f01bb1a7f0d21f66af5c1 100644 (file)
@@ -15,7 +15,7 @@
 /* Nothing to release.. */
 static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
-       char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data;
+       char *s=((struct autofs_symlink *)dentry->d_inode->i_private)->data;
        nd_set_link(nd, s);
        return NULL;
 }
index 11a6a9ae51b77442bd650a4d07574fee9a822336..800ce876caeca6e33fc427e40d34d89a69923ed3 100644 (file)
@@ -447,7 +447,6 @@ struct inode *autofs4_get_inode(struct super_block *sb,
                inode->i_uid = 0;
                inode->i_gid = 0;
        }
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 
index 5100f984783faa123caabf76ad97e1718bdea70e..27e17f96cada446d0858405493b46203fd0d57c3 100644 (file)
@@ -137,7 +137,9 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
                nd.flags = LOOKUP_DIRECTORY;
                ret = (dentry->d_op->d_revalidate)(dentry, &nd);
 
-               if (!ret) {
+               if (ret <= 0) {
+                       if (ret < 0)
+                               status = ret;
                        dcache_dir_close(inode, file);
                        goto out;
                }
@@ -400,13 +402,23 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
        int oz_mode = autofs4_oz_mode(sbi);
        int flags = nd ? nd->flags : 0;
-       int status = 0;
+       int status = 1;
 
        /* Pending dentry */
        if (autofs4_ispending(dentry)) {
-               if (!oz_mode)
-                       status = try_to_fill_dentry(dentry, flags);
-               return !status;
+               /* The daemon never causes a mount to trigger */
+               if (oz_mode)
+                       return 1;
+
+               /*
+                * A zero status is success otherwise we have a
+                * negative error code.
+                */
+               status = try_to_fill_dentry(dentry, flags);
+               if (status == 0)
+                               return 1;
+
+               return status;
        }
 
        /* Negative dentry.. invalidate if "old" */
@@ -421,9 +433,19 @@ static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
                DPRINTK("dentry=%p %.*s, emptydir",
                         dentry, dentry->d_name.len, dentry->d_name.name);
                spin_unlock(&dcache_lock);
-               if (!oz_mode)
-                       status = try_to_fill_dentry(dentry, flags);
-               return !status;
+               /* The daemon never causes a mount to trigger */
+               if (oz_mode)
+                       return 1;
+
+               /*
+                * A zero status is success otherwise we have a
+                * negative error code.
+                */
+               status = try_to_fill_dentry(dentry, flags);
+               if (status == 0)
+                       return 1;
+
+               return status;
        }
        spin_unlock(&dcache_lock);
 
index 50cfca5c7efd570588d549a5f23f9f5650fd360d..57020c7a7e6589fc84717d6015743bcbd9004627 100644 (file)
@@ -365,7 +365,6 @@ befs_read_inode(struct inode *inode)
        inode->i_mtime.tv_nsec = 0;   /* lower 16 bits are not a time */        
        inode->i_ctime = inode->i_mtime;
        inode->i_atime = inode->i_mtime;
-       inode->i_blksize = befs_sb->block_size;
 
        befs_ino->i_inode_num = fsrun_to_cpu(sb, raw_inode->inode_num);
        befs_ino->i_parent = fsrun_to_cpu(sb, raw_inode->parent);
@@ -446,9 +445,7 @@ befs_init_inodecache(void)
 static void
 befs_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(befs_inode_cachep))
-               printk(KERN_ERR "befs_destroy_inodecache: "
-                      "not all structures were freed\n");
+       kmem_cache_destroy(befs_inode_cachep);
 }
 
 /*
index 26fad96217380786af130867e2e8f943d670fe4b..dcf04cb132831c116cac8fe0de090a7106527a47 100644 (file)
@@ -102,7 +102,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
        inode->i_uid = current->fsuid;
        inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        inode->i_op = &bfs_file_inops;
        inode->i_fop = &bfs_file_operations;
        inode->i_mapping->a_ops = &bfs_aops;
index cf74f3d4d966d0f81c8abace34a1bfe79d9050e8..ed27ffb3459e9ea73ea23b476b27cf1bf95d0320 100644 (file)
@@ -76,7 +76,6 @@ static void bfs_read_inode(struct inode * inode)
        inode->i_size = BFS_FILESIZE(di);
        inode->i_blocks = BFS_FILEBLOCKS(di);
         if (inode->i_size || inode->i_blocks) dprintf("Registered inode with %lld size, %ld blocks\n", inode->i_size, inode->i_blocks);
-       inode->i_blksize = PAGE_SIZE;
        inode->i_atime.tv_sec =  le32_to_cpu(di->i_atime);
        inode->i_mtime.tv_sec =  le32_to_cpu(di->i_mtime);
        inode->i_ctime.tv_sec =  le32_to_cpu(di->i_ctime);
@@ -268,8 +267,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(bfs_inode_cachep))
-               printk(KERN_INFO "bfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(bfs_inode_cachep);
 }
 
 static struct super_operations bfs_sops = {
@@ -311,11 +309,10 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
        unsigned i, imap_len;
        struct bfs_sb_info * info;
 
-       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                return -ENOMEM;
        s->s_fs_info = info;
-       memset(info, 0, sizeof(*info));
 
        sb_set_blocksize(s, BFS_BSIZE);
 
@@ -338,10 +335,9 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
                        + BFS_ROOT_INO - 1;
 
        imap_len = info->si_lasti/8 + 1;
-       info->si_imap = kmalloc(imap_len, GFP_KERNEL);
+       info->si_imap = kzalloc(imap_len, GFP_KERNEL);
        if (!info->si_imap)
                goto out;
-       memset(info->si_imap, 0, imap_len);
        for (i=0; i<BFS_ROOT_INO; i++) 
                set_bit(i, info->si_imap);
 
index 64802aabd1aca5ff3a2a4f09679ad4cbca8e78d9..dfd8cfb7fb5dcd213ab74c41474c81e06a69f8e1 100644 (file)
@@ -515,7 +515,8 @@ static unsigned long randomize_stack_top(unsigned long stack_top)
 {
        unsigned int random_variable = 0;
 
-       if (current->flags & PF_RANDOMIZE) {
+       if ((current->flags & PF_RANDOMIZE) &&
+               !(current->personality & ADDR_NO_RANDOMIZE)) {
                random_variable = get_random_int() & STACK_RND_MASK;
                random_variable <<= PAGE_SHIFT;
        }
index 34ebbc191e46ada5e8c488257e9e131b0060cac3..66ba137f86618b25044a2beeb2a73a6f1dc81865 100644 (file)
@@ -507,7 +507,6 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
                inode->i_mode = mode;
                inode->i_uid = 0;
                inode->i_gid = 0;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime =
                        current_fs_time(inode->i_sb);
@@ -517,7 +516,7 @@ static struct inode *bm_get_inode(struct super_block *sb, int mode)
 
 static void bm_clear_inode(struct inode *inode)
 {
-       kfree(inode->u.generic_ip);
+       kfree(inode->i_private);
 }
 
 static void kill_node(Node *e)
@@ -545,7 +544,7 @@ static void kill_node(Node *e)
 static ssize_t
 bm_entry_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
 {
-       Node *e = file->f_dentry->d_inode->u.generic_ip;
+       Node *e = file->f_dentry->d_inode->i_private;
        loff_t pos = *ppos;
        ssize_t res;
        char *page;
@@ -579,7 +578,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
                                size_t count, loff_t *ppos)
 {
        struct dentry *root;
-       Node *e = file->f_dentry->d_inode->u.generic_ip;
+       Node *e = file->f_dentry->d_inode->i_private;
        int res = parse_command(buffer, count);
 
        switch (res) {
@@ -646,7 +645,7 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer,
        }
 
        e->dentry = dget(dentry);
-       inode->u.generic_ip = e;
+       inode->i_private = e;
        inode->i_fop = &bm_entry_operations;
 
        d_instantiate(dentry, inode);
index 3483d3cf80873432d7696f6f3f68b4adef928b01..0009346d827f52ad2da3c24bdbb6485d5cdfa6dd 100644 (file)
 #include <linux/kobj_map.h>
 #include <linux/cdev.h>
 #include <linux/mutex.h>
+#include <linux/backing-dev.h>
 
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
 
+/*
+ * capabilities for /dev/mem, /dev/kmem and similar directly mappable character
+ * devices
+ * - permits shared-mmap for read, write and/or exec
+ * - does not permit private mmap in NOMMU mode (can't do COW)
+ * - no readahead or I/O queue unplugging required
+ */
+struct backing_dev_info directly_mappable_cdev_bdi = {
+       .capabilities   = (
+#ifdef CONFIG_MMU
+               /* permit private copies of the data to be taken */
+               BDI_CAP_MAP_COPY |
+#endif
+               /* permit direct mmap, for read, write or exec */
+               BDI_CAP_MAP_DIRECT |
+               BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP),
+};
+
 static struct kobj_map *cdev_map;
 
 static DEFINE_MUTEX(chrdevs_lock);
@@ -461,3 +480,4 @@ EXPORT_SYMBOL(cdev_del);
 EXPORT_SYMBOL(cdev_add);
 EXPORT_SYMBOL(register_chrdev);
 EXPORT_SYMBOL(unregister_chrdev);
+EXPORT_SYMBOL(directly_mappable_cdev_bdi);
index c3ef1c0d0e684786969bdb1c1caf7e860e2afd9e..22bcf4d7e7aed4e700bb75e846df73a8480316d4 100644 (file)
@@ -253,7 +253,6 @@ cifs_alloc_inode(struct super_block *sb)
        file data or metadata */
        cifs_inode->clientCanCacheRead = FALSE;
        cifs_inode->clientCanCacheAll = FALSE;
-       cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE;
        cifs_inode->vfs_inode.i_blkbits = 14;  /* 2**14 = CIFS_MAX_MSGSIZE */
        cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME;
        INIT_LIST_HEAD(&cifs_inode->openFileList);
@@ -699,8 +698,7 @@ cifs_init_inodecache(void)
 static void
 cifs_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(cifs_inode_cachep))
-               printk(KERN_WARNING "cifs_inode_cache: error freeing\n");
+       kmem_cache_destroy(cifs_inode_cachep);
 }
 
 static int
@@ -778,13 +776,9 @@ static void
 cifs_destroy_request_bufs(void)
 {
        mempool_destroy(cifs_req_poolp);
-       if (kmem_cache_destroy(cifs_req_cachep))
-               printk(KERN_WARNING
-                      "cifs_destroy_request_cache: error not all structures were freed\n");
+       kmem_cache_destroy(cifs_req_cachep);
        mempool_destroy(cifs_sm_req_poolp);
-       if (kmem_cache_destroy(cifs_sm_req_cachep))
-               printk(KERN_WARNING
-                     "cifs_destroy_request_cache: cifs_small_rq free error\n");
+       kmem_cache_destroy(cifs_sm_req_cachep);
 }
 
 static int
@@ -819,13 +813,8 @@ static void
 cifs_destroy_mids(void)
 {
        mempool_destroy(cifs_mid_poolp);
-       if (kmem_cache_destroy(cifs_mid_cachep))
-               printk(KERN_WARNING
-                      "cifs_destroy_mids: error not all structures were freed\n");
-
-       if (kmem_cache_destroy(cifs_oplock_cachep))
-               printk(KERN_WARNING
-                      "error not all oplock structures were freed\n");
+       kmem_cache_destroy(cifs_mid_cachep);
+       kmem_cache_destroy(cifs_oplock_cachep);
 }
 
 static int cifs_oplock_thread(void * dummyarg)
index 9aeb58a7d369380d3f81a5f63569c66405af2463..b27b34537bf23c2bf3bbc566c1155c3d331df7a1 100644 (file)
@@ -216,10 +216,9 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
 
        if (allocation_size < end_of_file)
                cFYI(1, ("May be sparse file, allocation less than file size"));
-       cFYI(1, ("File Size %ld and blocks %llu and blocksize %ld",
+       cFYI(1, ("File Size %ld and blocks %llu",
                (unsigned long)tmp_inode->i_size,
-               (unsigned long long)tmp_inode->i_blocks,
-               tmp_inode->i_blksize));
+               (unsigned long long)tmp_inode->i_blocks));
        if (S_ISREG(tmp_inode->i_mode)) {
                cFYI(1, ("File inode"));
                tmp_inode->i_op = &cifs_file_inode_ops;
index 5597080cb8114a0ea0eb6f020f7fc285f37a1b57..95a54253c0479989ec20f047d4bd821ecd5adf30 100644 (file)
@@ -110,8 +110,6 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
                inode->i_nlink = attr->va_nlink;
        if (attr->va_size != -1)
                inode->i_size = attr->va_size;
-       if (attr->va_blocksize != -1)
-               inode->i_blksize = attr->va_blocksize;
        if (attr->va_size != -1)
                inode->i_blocks = (attr->va_size + 511) >> 9;
        if (attr->va_atime.tv_sec != -1) 
index 71f2ea632e5376168d5b8aa4f194604941021104..8651ea6a23b727c1c27b24b0d9a3b9d03c062fa0 100644 (file)
@@ -513,7 +513,7 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir,
        ino_t ino;
        int ret, i;
 
-       vdir = (struct venus_dirent *)kmalloc(sizeof(*vdir), GFP_KERNEL);
+       vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
        if (!vdir) return -ENOMEM;
 
        i = filp->f_pos;
index 87f1dc8aa24b1c21f110f12701f0b8551e1a9b45..88d12332116489bd6dc2cb475dc8727cffe88a18 100644 (file)
@@ -80,8 +80,7 @@ int coda_init_inodecache(void)
 
 void coda_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(coda_inode_cachep))
-               printk(KERN_INFO "coda_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(coda_inode_cachep);
 }
 
 static int coda_remount(struct super_block *sb, int *flags, char *data)
index e31e9cf966475dd27b1aa206437b4330e80a0d70..ce982f6e8c80270be3fd23f8f9553c486626986e 100644 (file)
@@ -1855,7 +1855,7 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
 
        } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
 
-       if (tsp && !(current->personality & STICKY_TIMEOUTS)) {
+       if (ret == 0 && tsp && !(current->personality & STICKY_TIMEOUTS)) {
                struct compat_timespec rts;
 
                rts.tv_sec = timeout / HZ;
@@ -1866,7 +1866,8 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
                }
                if (compat_timespec_compare(&rts, &ts) >= 0)
                        rts = ts;
-               copy_to_user(tsp, &rts, sizeof(rts));
+               if (copy_to_user(tsp, &rts, sizeof(rts)))
+                       ret = -EFAULT;
        }
 
        if (ret == -ERESTARTNOHAND) {
index f499803743e04add3d576dc919e0a54752d00ba1..85105e50f7db668702b36ea78a32feaa6ef12593 100644 (file)
@@ -274,9 +274,8 @@ static int check_perm(struct inode * inode, struct file * file)
        /* No error? Great, allocate a buffer for the file, and store it
         * it in file->private_data for easy access.
         */
-       buffer = kmalloc(sizeof(struct configfs_buffer),GFP_KERNEL);
+       buffer = kzalloc(sizeof(struct configfs_buffer),GFP_KERNEL);
        if (buffer) {
-               memset(buffer,0,sizeof(struct configfs_buffer));
                init_MUTEX(&buffer->sem);
                buffer->needs_read_fill = 1;
                buffer->ops = ops;
index e14488ca6411fef8db1fb86e1252f49b99f9b2a7..fb18917954a91f95643b38352adab17a42e98600 100644 (file)
@@ -76,11 +76,10 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
 
        if (!sd_iattr) {
                /* setting attributes for the first time, allocate now */
-               sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+               sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL);
                if (!sd_iattr)
                        return -ENOMEM;
                /* assign default attributes */
-               memset(sd_iattr, 0, sizeof(struct iattr));
                sd_iattr->ia_mode = sd->s_mode;
                sd_iattr->ia_uid = 0;
                sd_iattr->ia_gid = 0;
@@ -136,7 +135,6 @@ struct inode * configfs_new_inode(mode_t mode, struct configfs_dirent * sd)
 {
        struct inode * inode = new_inode(configfs_sb);
        if (inode) {
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->a_ops = &configfs_aops;
                inode->i_mapping->backing_dev_info = &configfs_backing_dev_info;
index 223c0431042deaa8fb77aa99626100338e546f4e..ad96b69907156c5e79879da38a4d928a47fa8b8e 100644 (file)
@@ -73,7 +73,6 @@ static int cramfs_iget5_set(struct inode *inode, void *opaque)
        inode->i_uid = cramfs_inode->uid;
        inode->i_size = cramfs_inode->size;
        inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_gid = cramfs_inode->gid;
        /* Struct copy intentional */
        inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
@@ -242,11 +241,10 @@ static int cramfs_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_flags |= MS_RDONLY;
 
-       sbi = kmalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct cramfs_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct cramfs_sb_info));
 
        /* Invalidate the read buffers on mount: think disk change.. */
        mutex_lock(&read_mutex);
index 39640fd034580f66c8f58ed9329e8220d4392c07..bf3901ab1744b25355ca54ea82deb578f8aeffc0 100644 (file)
@@ -32,8 +32,8 @@ static ssize_t default_write_file(struct file *file, const char __user *buf,
 
 static int default_open(struct inode *inode, struct file *file)
 {
-       if (inode->u.generic_ip)
-               file->private_data = inode->u.generic_ip;
+       if (inode->i_private)
+               file->private_data = inode->i_private;
 
        return 0;
 }
@@ -55,12 +55,11 @@ static u64 debugfs_u8_get(void *data)
 DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
 
 /**
- * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write an unsigned 8 bit value.
- *
+ * debugfs_create_u8 - create a debugfs file that is used to read and write an unsigned 8-bit value
  * @name: a pointer to a string containing the name of the file to create.
  * @mode: the permission that the file should have
  * @parent: a pointer to the parent dentry for this file.  This should be a
- *          directory dentry if set.  If this paramater is NULL, then the
+ *          directory dentry if set.  If this parameter is %NULL, then the
  *          file will be created in the root of the debugfs filesystem.
  * @value: a pointer to the variable that the file should read to and write
  *         from.
@@ -72,11 +71,11 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file 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.
+ * 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
+ * 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
+ * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
  * code.
  */
 struct dentry *debugfs_create_u8(const char *name, mode_t mode,
@@ -97,12 +96,11 @@ static u64 debugfs_u16_get(void *data)
 DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
 
 /**
- * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write an unsigned 16 bit value.
- *
+ * debugfs_create_u16 - create a debugfs file that is used to read and write an unsigned 16-bit value
  * @name: a pointer to a string containing the name of the file to create.
  * @mode: the permission that the file should have
  * @parent: a pointer to the parent dentry for this file.  This should be a
- *          directory dentry if set.  If this paramater is NULL, then the
+ *          directory dentry if set.  If this parameter is %NULL, then the
  *          file will be created in the root of the debugfs filesystem.
  * @value: a pointer to the variable that the file should read to and write
  *         from.
@@ -114,11 +112,11 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file 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.
+ * 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
+ * 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
+ * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
  * code.
  */
 struct dentry *debugfs_create_u16(const char *name, mode_t mode,
@@ -139,12 +137,11 @@ static u64 debugfs_u32_get(void *data)
 DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
 
 /**
- * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write an unsigned 32 bit value.
- *
+ * debugfs_create_u32 - create a debugfs file that is used to read and write an unsigned 32-bit value
  * @name: a pointer to a string containing the name of the file to create.
  * @mode: the permission that the file should have
  * @parent: a pointer to the parent dentry for this file.  This should be a
- *          directory dentry if set.  If this paramater is NULL, then the
+ *          directory dentry if set.  If this parameter is %NULL, then the
  *          file will be created in the root of the debugfs filesystem.
  * @value: a pointer to the variable that the file should read to and write
  *         from.
@@ -156,11 +153,11 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file 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.
+ * 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
+ * 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
+ * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
  * code.
  */
 struct dentry *debugfs_create_u32(const char *name, mode_t mode,
@@ -219,12 +216,11 @@ static const struct file_operations fops_bool = {
 };
 
 /**
- * debugfs_create_bool - create a file in the debugfs filesystem that is used to read and write a boolean value.
- *
+ * debugfs_create_bool - create a debugfs file that is used to read and write a boolean value
  * @name: a pointer to a string containing the name of the file to create.
  * @mode: the permission that the file should have
  * @parent: a pointer to the parent dentry for this file.  This should be a
- *          directory dentry if set.  If this paramater is NULL, then the
+ *          directory dentry if set.  If this parameter is %NULL, then the
  *          file will be created in the root of the debugfs filesystem.
  * @value: a pointer to the variable that the file should read to and write
  *         from.
@@ -236,11 +232,11 @@ static const struct file_operations fops_bool = {
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file 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.
+ * 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
+ * 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
+ * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
  * code.
  */
 struct dentry *debugfs_create_bool(const char *name, mode_t mode,
@@ -264,13 +260,11 @@ static struct file_operations fops_blob = {
 };
 
 /**
- * debugfs_create_blob - create a file in the debugfs filesystem that is
- * used to read and write a binary blob.
- *
+ * debugfs_create_blob - create a debugfs file that is used to read and write a binary blob
  * @name: a pointer to a string containing the name of the file to create.
  * @mode: the permission that the file should have
  * @parent: a pointer to the parent dentry for this file.  This should be a
- *          directory dentry if set.  If this paramater is NULL, then the
+ *          directory dentry if set.  If this parameter is %NULL, then the
  *          file will be created in the root of the debugfs filesystem.
  * @blob: a pointer to a struct debugfs_blob_wrapper which contains a pointer
  *        to the blob data and the size of the data.
@@ -282,11 +276,11 @@ static struct file_operations fops_blob = {
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file 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.
+ * 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
+ * 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
+ * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
  * code.
  */
 struct dentry *debugfs_create_blob(const char *name, mode_t mode,
index e8ae3042b806464649ceb767b721a0e7b4d9fa79..269e649e6dc6b6e1f891bc2aaf4f11aa03b58dec 100644 (file)
@@ -40,7 +40,6 @@ static struct inode *debugfs_get_inode(struct super_block *sb, int mode, dev_t d
                inode->i_mode = mode;
                inode->i_uid = 0;
                inode->i_gid = 0;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                switch (mode & S_IFMT) {
@@ -162,14 +161,13 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
 
 /**
  * debugfs_create_file - create a file in the debugfs filesystem
- *
  * @name: a pointer to a string containing the name of the file to create.
  * @mode: the permission that the file should have
  * @parent: a pointer to the parent dentry for this file.  This should be a
  *          directory dentry if set.  If this paramater is NULL, then the
  *          file will be created in the root of the debugfs filesystem.
  * @data: a pointer to something that the caller will want to get to later
- *        on.  The inode.u.generic_ip pointer will point to this value on
+ *        on.  The inode.i_private pointer will point to this value on
  *        the open() call.
  * @fops: a pointer to a struct file_operations that should be used for
  *        this file.
@@ -182,11 +180,11 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file 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.
+ * 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
+ * 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
+ * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
  * code.
  */
 struct dentry *debugfs_create_file(const char *name, mode_t mode,
@@ -210,7 +208,7 @@ struct dentry *debugfs_create_file(const char *name, mode_t mode,
 
        if (dentry->d_inode) {
                if (data)
-                       dentry->d_inode->u.generic_ip = data;
+                       dentry->d_inode->i_private = data;
                if (fops)
                        dentry->d_inode->i_fop = fops;
        }
@@ -221,7 +219,6 @@ EXPORT_SYMBOL_GPL(debugfs_create_file);
 
 /**
  * debugfs_create_dir - create a directory in the debugfs filesystem
- *
  * @name: a pointer to a string containing the name of the directory to
  *        create.
  * @parent: a pointer to the parent dentry for this file.  This should be a
@@ -233,11 +230,11 @@ EXPORT_SYMBOL_GPL(debugfs_create_file);
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file 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.
+ * 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
+ * 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
+ * %NULL or !%NULL instead as to eliminate the need for #ifdef in the calling
  * code.
  */
 struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
@@ -250,7 +247,6 @@ EXPORT_SYMBOL_GPL(debugfs_create_dir);
 
 /**
  * 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
  *          removed.
  *
index f7aef5bb584a7deb5736f556da5b9155b754a760..5f7b5a6025bfec943dc390f02bcaa92ef7201b1e 100644 (file)
@@ -113,7 +113,6 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
        inode->i_ino = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        inode->i_blocks = 0;
-       inode->i_blksize = 1024;
        inode->i_uid = inode->i_gid = 0;
        inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
        inode->i_op = &simple_dir_inode_operations;
@@ -172,12 +171,11 @@ int devpts_pty_new(struct tty_struct *tty)
                return -ENOMEM;
 
        inode->i_ino = number+2;
-       inode->i_blksize = 1024;
        inode->i_uid = config.setuid ? config.uid : current->fsuid;
        inode->i_gid = config.setgid ? config.gid : current->fsgid;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        init_special_inode(inode, S_IFCHR|config.mode, device);
-       inode->u.generic_ip = tty;
+       inode->i_private = tty;
 
        dentry = get_node(number);
        if (!IS_ERR(dentry) && !dentry->d_inode)
@@ -196,7 +194,7 @@ struct tty_struct *devpts_get_tty(int number)
        tty = NULL;
        if (!IS_ERR(dentry)) {
                if (dentry->d_inode)
-                       tty = dentry->d_inode->u.generic_ip;
+                       tty = dentry->d_inode->i_private;
                dput(dentry);
        }
 
index 8ac2462ae5dd28b45b7e5e27e5216df85be43e9f..b3f50651eb6bd1a979a2d2442c4294b48141780b 100644 (file)
@@ -90,8 +90,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(efs_inode_cachep))
-               printk(KERN_INFO "efs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(efs_inode_cachep);
 }
 
 static void efs_put_super(struct super_block *s)
@@ -248,11 +247,10 @@ static int efs_fill_super(struct super_block *s, void *d, int silent)
        struct buffer_head *bh;
        struct inode *root;
 
-       sb = kmalloc(sizeof(struct efs_sb_info), GFP_KERNEL);
+       sb = kzalloc(sizeof(struct efs_sb_info), GFP_KERNEL);
        if (!sb)
                return -ENOMEM;
        s->s_fs_info = sb;
-       memset(sb, 0, sizeof(struct efs_sb_info));
  
        s->s_magic              = EFS_SUPER_MAGIC;
        if (!sb_set_blocksize(s, EFS_BLOCKSIZE)) {
index 3a3567433b921795c9ba6a7fe879a9b6760c923f..8d544334bcd22d216b057620900834e73b756698 100644 (file)
@@ -1590,7 +1590,6 @@ static struct inode *ep_eventpoll_inode(void)
        inode->i_uid = current->fsuid;
        inode->i_gid = current->fsgid;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-       inode->i_blksize = PAGE_SIZE;
        return inode;
 
 eexit_1:
index 54135df2a9662cbf1f222ee468067812f52e1f72..97df6e0aeaeed58db0f63ab746883ee87c7c1985 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -595,7 +595,7 @@ static int de_thread(struct task_struct *tsk)
        if (!newsighand)
                return -ENOMEM;
 
-       if (thread_group_empty(current))
+       if (thread_group_empty(tsk))
                goto no_thread_group;
 
        /*
@@ -620,17 +620,17 @@ static int de_thread(struct task_struct *tsk)
         * Reparenting needs write_lock on tasklist_lock,
         * so it is safe to do it under read_lock.
         */
-       if (unlikely(current->group_leader == child_reaper))
-               child_reaper = current;
+       if (unlikely(tsk->group_leader == child_reaper))
+               child_reaper = tsk;
 
-       zap_other_threads(current);
+       zap_other_threads(tsk);
        read_unlock(&tasklist_lock);
 
        /*
         * Account for the thread group leader hanging around:
         */
        count = 1;
-       if (!thread_group_leader(current)) {
+       if (!thread_group_leader(tsk)) {
                count = 2;
                /*
                 * The SIGALRM timer survives the exec, but needs to point
@@ -639,14 +639,14 @@ static int de_thread(struct task_struct *tsk)
                 * synchronize with any firing (by calling del_timer_sync)
                 * before we can safely let the old group leader die.
                 */
-               sig->tsk = current;
+               sig->tsk = tsk;
                spin_unlock_irq(lock);
                if (hrtimer_cancel(&sig->real_timer))
                        hrtimer_restart(&sig->real_timer);
                spin_lock_irq(lock);
        }
        while (atomic_read(&sig->count) > count) {
-               sig->group_exit_task = current;
+               sig->group_exit_task = tsk;
                sig->notify_count = count;
                __set_current_state(TASK_UNINTERRUPTIBLE);
                spin_unlock_irq(lock);
@@ -662,13 +662,13 @@ static int de_thread(struct task_struct *tsk)
         * do is to wait for the thread group leader to become inactive,
         * and to assume its PID:
         */
-       if (!thread_group_leader(current)) {
+       if (!thread_group_leader(tsk)) {
                /*
                 * Wait for the thread group leader to be a zombie.
                 * It should already be zombie at this point, most
                 * of the time.
                 */
-               leader = current->group_leader;
+               leader = tsk->group_leader;
                while (leader->exit_state != EXIT_ZOMBIE)
                        yield();
 
@@ -682,12 +682,12 @@ static int de_thread(struct task_struct *tsk)
                 * When we take on its identity by switching to its PID, we
                 * also take its birthdate (always earlier than our own).
                 */
-               current->start_time = leader->start_time;
+               tsk->start_time = leader->start_time;
 
                write_lock_irq(&tasklist_lock);
 
-               BUG_ON(leader->tgid != current->tgid);
-               BUG_ON(current->pid == current->tgid);
+               BUG_ON(leader->tgid != tsk->tgid);
+               BUG_ON(tsk->pid == tsk->tgid);
                /*
                 * An exec() starts a new thread group with the
                 * TGID of the previous thread group. Rehash the
@@ -696,24 +696,21 @@ static int de_thread(struct task_struct *tsk)
                 */
 
                /* Become a process group leader with the old leader's pid.
-                * Note: The old leader also uses thispid until release_task
+                * The old leader becomes a thread of the this thread group.
+                * Note: The old leader also uses this pid until release_task
                 *       is called.  Odd but simple and correct.
                 */
-               detach_pid(current, PIDTYPE_PID);
-               current->pid = leader->pid;
-               attach_pid(current, PIDTYPE_PID,  current->pid);
-               attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
-               attach_pid(current, PIDTYPE_SID,  current->signal->session);
-               list_replace_rcu(&leader->tasks, &current->tasks);
+               detach_pid(tsk, PIDTYPE_PID);
+               tsk->pid = leader->pid;
+               attach_pid(tsk, PIDTYPE_PID,  tsk->pid);
+               transfer_pid(leader, tsk, PIDTYPE_PGID);
+               transfer_pid(leader, tsk, PIDTYPE_SID);
+               list_replace_rcu(&leader->tasks, &tsk->tasks);
 
-               current->group_leader = current;
-               leader->group_leader = current;
+               tsk->group_leader = tsk;
+               leader->group_leader = tsk;
 
-               /* Reduce leader to a thread */
-               detach_pid(leader, PIDTYPE_PGID);
-               detach_pid(leader, PIDTYPE_SID);
-
-               current->exit_signal = SIGCHLD;
+               tsk->exit_signal = SIGCHLD;
 
                BUG_ON(leader->exit_state != EXIT_ZOMBIE);
                leader->exit_state = EXIT_DEAD;
@@ -753,7 +750,7 @@ no_thread_group:
                spin_lock(&oldsighand->siglock);
                spin_lock_nested(&newsighand->siglock, SINGLE_DEPTH_NESTING);
 
-               rcu_assign_pointer(current->sighand, newsighand);
+               rcu_assign_pointer(tsk->sighand, newsighand);
                recalc_sigpending();
 
                spin_unlock(&newsighand->siglock);
@@ -764,7 +761,7 @@ no_thread_group:
                        kmem_cache_free(sighand_cachep, oldsighand);
        }
 
-       BUG_ON(!thread_group_leader(current));
+       BUG_ON(!thread_group_leader(tsk));
        return 0;
 }
        
index da52b4a5db64005173124575e63161ed1d6c3d35..7c420b800c3438fd02ab669368f48fb9a6f01c5a 100644 (file)
@@ -89,8 +89,8 @@ ext2_acl_to_disk(const struct posix_acl *acl, size_t *size)
        size_t n;
 
        *size = ext2_acl_size(acl->a_count);
-       ext_acl = (ext2_acl_header *)kmalloc(sizeof(ext2_acl_header) +
-               acl->a_count * sizeof(ext2_acl_entry), GFP_KERNEL);
+       ext_acl = kmalloc(sizeof(ext2_acl_header) + acl->a_count *
+                       sizeof(ext2_acl_entry), GFP_KERNEL);
        if (!ext_acl)
                return ERR_PTR(-ENOMEM);
        ext_acl->a_version = cpu_to_le32(EXT2_ACL_VERSION);
index 695f69ccf9088a072e4a899ec431629a14d44ebd..2cb545bf0f3c42dba436626c2832bed511e1f7fb 100644 (file)
@@ -574,7 +574,6 @@ got:
        inode->i_mode = mode;
 
        inode->i_ino = ino;
-       inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size (for stat), not the fs block size */
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
        memset(ei->i_data, 0, sizeof(ei->i_data));
index fb4d3220eb8d717918445b13d8f920023e3a13fb..dd4e14c221e0e07c67c96e2ae06e6c3b755f225e 100644 (file)
@@ -1094,7 +1094,6 @@ void ext2_read_inode (struct inode * inode)
                brelse (bh);
                goto bad_inode;
        }
-       inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size (for stat), not the fs block size */
        inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
        ei->i_flags = le32_to_cpu(raw_inode->i_flags);
        ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
index 4286ff6330b6a0b006ca159e5041b6e75ed2075b..513cd421ac0b6627da069f16a1274154500a8374 100644 (file)
@@ -184,8 +184,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(ext2_inode_cachep))
-               printk(KERN_INFO "ext2_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(ext2_inode_cachep);
 }
 
 static void ext2_clear_inode(struct inode *inode)
@@ -544,17 +543,24 @@ static int ext2_check_descriptors (struct super_block * sb)
        int i;
        int desc_block = 0;
        struct ext2_sb_info *sbi = EXT2_SB(sb);
-       unsigned long block = le32_to_cpu(sbi->s_es->s_first_data_block);
+       unsigned long first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+       unsigned long last_block;
        struct ext2_group_desc * gdp = NULL;
 
        ext2_debug ("Checking group descriptors");
 
        for (i = 0; i < sbi->s_groups_count; i++)
        {
+               if (i == sbi->s_groups_count - 1)
+                       last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
+               else
+                       last_block = first_block +
+                               (EXT2_BLOCKS_PER_GROUP(sb) - 1);
+
                if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
                        gdp = (struct ext2_group_desc *) sbi->s_group_desc[desc_block++]->b_data;
-               if (le32_to_cpu(gdp->bg_block_bitmap) < block ||
-                   le32_to_cpu(gdp->bg_block_bitmap) >= block + EXT2_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
+                   le32_to_cpu(gdp->bg_block_bitmap) > last_block)
                {
                        ext2_error (sb, "ext2_check_descriptors",
                                    "Block bitmap for group %d"
@@ -562,8 +568,8 @@ static int ext2_check_descriptors (struct super_block * sb)
                                    i, (unsigned long) le32_to_cpu(gdp->bg_block_bitmap));
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||
-                   le32_to_cpu(gdp->bg_inode_bitmap) >= block + EXT2_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||
+                   le32_to_cpu(gdp->bg_inode_bitmap) > last_block)
                {
                        ext2_error (sb, "ext2_check_descriptors",
                                    "Inode bitmap for group %d"
@@ -571,9 +577,9 @@ static int ext2_check_descriptors (struct super_block * sb)
                                    i, (unsigned long) le32_to_cpu(gdp->bg_inode_bitmap));
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_table) < block ||
-                   le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >=
-                   block + EXT2_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
+                   le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >
+                   last_block)
                {
                        ext2_error (sb, "ext2_check_descriptors",
                                    "Inode table for group %d"
@@ -581,7 +587,7 @@ static int ext2_check_descriptors (struct super_block * sb)
                                    i, (unsigned long) le32_to_cpu(gdp->bg_inode_table));
                        return 0;
                }
-               block += EXT2_BLOCKS_PER_GROUP(sb);
+               first_block += EXT2_BLOCKS_PER_GROUP(sb);
                gdp++;
        }
        return 1;
@@ -648,11 +654,10 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        int i, j;
        __le32 features;
 
-       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(*sbi));
 
        /*
         * See what the current blocksize for the device is, and
@@ -861,10 +866,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
 
        if (EXT2_BLOCKS_PER_GROUP(sb) == 0)
                goto cantfind_ext2;
-       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
-                                       le32_to_cpu(es->s_first_data_block) +
-                                      EXT2_BLOCKS_PER_GROUP(sb) - 1) /
-                                      EXT2_BLOCKS_PER_GROUP(sb);
+       sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
+                               le32_to_cpu(es->s_first_data_block) - 1)
+                                       / EXT2_BLOCKS_PER_GROUP(sb)) + 1;
        db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
                   EXT2_DESC_PER_BLOCK(sb);
        sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
index 86ae8e93adb9d84dadbace346c65f0c5b09952fa..af52a7f8b291d0baf3542246fb90703032cfbecc 100644 (file)
@@ -521,11 +521,10 @@ bad_block:                ext2_error(sb, "ext2_xattr_set",
                }
        } else {
                /* Allocate a buffer where we construct the new block. */
-               header = kmalloc(sb->s_blocksize, GFP_KERNEL);
+               header = kzalloc(sb->s_blocksize, GFP_KERNEL);
                error = -ENOMEM;
                if (header == NULL)
                        goto cleanup;
-               memset(header, 0, sb->s_blocksize);
                end = (char *)header + sb->s_blocksize;
                header->h_magic = cpu_to_le32(EXT2_XATTR_MAGIC);
                header->h_blocks = header->h_refcount = cpu_to_le32(1);
index 0d21d558b87a19d2105d32ff8df19698ffe439a5..1e5038d9a01b9f469015b83f8ee7eb07a9abf8f8 100644 (file)
@@ -90,8 +90,8 @@ ext3_acl_to_disk(const struct posix_acl *acl, size_t *size)
        size_t n;
 
        *size = ext3_acl_size(acl->a_count);
-       ext_acl = (ext3_acl_header *)kmalloc(sizeof(ext3_acl_header) +
-               acl->a_count * sizeof(ext3_acl_entry), GFP_KERNEL);
+       ext_acl = kmalloc(sizeof(ext3_acl_header) + acl->a_count *
+                       sizeof(ext3_acl_entry), GFP_KERNEL);
        if (!ext_acl)
                return ERR_PTR(-ENOMEM);
        ext_acl->a_version = cpu_to_le32(EXT3_ACL_VERSION);
@@ -258,7 +258,7 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
                default:
                        return -EINVAL;
        }
-       if (acl) {
+       if (acl) {
                value = ext3_acl_to_disk(acl, &size);
                if (IS_ERR(value))
                        return (int)PTR_ERR(value);
index 063d994bda0b2c42f49571c5893f514c82898459..b41a7d7e20f006bc7e85a6e4b2315cf38ee2fdc9 100644 (file)
 
 #define in_range(b, first, len)        ((b) >= (first) && (b) <= (first) + (len) - 1)
 
+/**
+ * ext3_get_group_desc() -- load group descriptor from disk
+ * @sb:                        super block
+ * @block_group:       given block group
+ * @bh:                        pointer to the buffer head to store the block
+ *                     group descriptor
+ */
 struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
                                             unsigned int block_group,
                                             struct buffer_head ** bh)
@@ -73,8 +80,12 @@ struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb,
        return desc + offset;
 }
 
-/*
- * Read the bitmap for a given block_group, reading into the specified 
+/**
+ * read_block_bitmap()
+ * @sb:                        super block
+ * @block_group:       given block group
+ *
+ * Read the bitmap for a given block_group, reading into the specified
  * slot in the superblock's bitmap cache.
  *
  * Return buffer_head on success or NULL in case of failure.
@@ -103,15 +114,22 @@ error_out:
  * Operations include:
  * dump, find, add, remove, is_empty, find_next_reservable_window, etc.
  *
- * We use sorted double linked list for the per-filesystem reservation
- * window list. (like in vm_region).
+ * We use a red-black tree to represent per-filesystem reservation
+ * windows.
+ *
+ */
+
+/**
+ * __rsv_window_dump() -- Dump the filesystem block allocation reservation map
+ * @rb_root:           root of per-filesystem reservation rb tree
+ * @verbose:           verbose mode
+ * @fn:                        function which wishes to dump the reservation map
  *
- * Initially, we keep those small operations in the abstract functions,
- * so later if we need a better searching tree than double linked-list,
- * we could easily switch to that without changing too much
- * code.
+ * If verbose is turned on, it will print the whole block reservation
+ * windows(start, end).        Otherwise, it will only print out the "bad" windows,
+ * those windows that overlap with their immediate neighbors.
  */
-#if 0
+#if 1
 static void __rsv_window_dump(struct rb_root *root, int verbose,
                              const char *fn)
 {
@@ -129,7 +147,7 @@ restart:
                rsv = list_entry(n, struct ext3_reserve_window_node, rsv_node);
                if (verbose)
                        printk("reservation window 0x%p "
-                              "start:  %d, end:  %d\n",
+                              "start:  %lu, end:  %lu\n",
                               rsv, rsv->rsv_start, rsv->rsv_end);
                if (rsv->rsv_start && rsv->rsv_start >= rsv->rsv_end) {
                        printk("Bad reservation %p (start >= end)\n",
@@ -161,6 +179,22 @@ restart:
 #define rsv_window_dump(root, verbose) do {} while (0)
 #endif
 
+/**
+ * goal_in_my_reservation()
+ * @rsv:               inode's reservation window
+ * @grp_goal:          given goal block relative to the allocation block group
+ * @group:             the current allocation block group
+ * @sb:                        filesystem super block
+ *
+ * Test if the given goal block (group relative) is within the file's
+ * own block reservation window range.
+ *
+ * If the reservation window is outside the goal allocation group, return 0;
+ * grp_goal (given goal block) could be -1, which means no specific
+ * goal block. In this case, always return 1.
+ * If the goal block is within the reservation window, return 1;
+ * otherwise, return 0;
+ */
 static int
 goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal,
                        unsigned int group, struct super_block * sb)
@@ -168,7 +202,7 @@ goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal,
        ext3_fsblk_t group_first_block, group_last_block;
 
        group_first_block = ext3_group_first_block_no(sb, group);
-       group_last_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1;
+       group_last_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1);
 
        if ((rsv->_rsv_start > group_last_block) ||
            (rsv->_rsv_end < group_first_block))
@@ -179,7 +213,11 @@ goal_in_my_reservation(struct ext3_reserve_window *rsv, ext3_grpblk_t grp_goal,
        return 1;
 }
 
-/*
+/**
+ * search_reserve_window()
+ * @rb_root:           root of reservation tree
+ * @goal:              target allocation block
+ *
  * Find the reserved window which includes the goal, or the previous one
  * if the goal is not in any window.
  * Returns NULL if there are no windows or if all windows start after the goal.
@@ -216,6 +254,13 @@ search_reserve_window(struct rb_root *root, ext3_fsblk_t goal)
        return rsv;
 }
 
+/**
+ * ext3_rsv_window_add() -- Insert a window to the block reservation rb tree.
+ * @sb:                        super block
+ * @rsv:               reservation window to add
+ *
+ * Must be called with rsv_lock hold.
+ */
 void ext3_rsv_window_add(struct super_block *sb,
                    struct ext3_reserve_window_node *rsv)
 {
@@ -236,14 +281,25 @@ void ext3_rsv_window_add(struct super_block *sb,
                        p = &(*p)->rb_left;
                else if (start > this->rsv_end)
                        p = &(*p)->rb_right;
-               else
+               else {
+                       rsv_window_dump(root, 1);
                        BUG();
+               }
        }
 
        rb_link_node(node, parent, p);
        rb_insert_color(node, root);
 }
 
+/**
+ * ext3_rsv_window_remove() -- unlink a window from the reservation rb tree
+ * @sb:                        super block
+ * @rsv:               reservation window to remove
+ *
+ * Mark the block reservation window as not allocated, and unlink it
+ * from the filesystem reservation window rb tree. Must be called with
+ * rsv_lock hold.
+ */
 static void rsv_window_remove(struct super_block *sb,
                              struct ext3_reserve_window_node *rsv)
 {
@@ -253,11 +309,39 @@ static void rsv_window_remove(struct super_block *sb,
        rb_erase(&rsv->rsv_node, &EXT3_SB(sb)->s_rsv_window_root);
 }
 
+/*
+ * rsv_is_empty() -- Check if the reservation window is allocated.
+ * @rsv:               given reservation window to check
+ *
+ * returns 1 if the end block is EXT3_RESERVE_WINDOW_NOT_ALLOCATED.
+ */
 static inline int rsv_is_empty(struct ext3_reserve_window *rsv)
 {
        /* a valid reservation end block could not be 0 */
-       return (rsv->_rsv_end == EXT3_RESERVE_WINDOW_NOT_ALLOCATED);
+       return rsv->_rsv_end == EXT3_RESERVE_WINDOW_NOT_ALLOCATED;
 }
+
+/**
+ * ext3_init_block_alloc_info()
+ * @inode:             file inode structure
+ *
+ * Allocate and initialize the reservation window structure, and
+ * link the window to the ext3 inode structure at last
+ *
+ * The reservation window structure is only dynamically allocated
+ * and linked to ext3 inode the first time the open file
+ * needs a new block. So, before every ext3_new_block(s) call, for
+ * regular files, we should check whether the reservation window
+ * structure exists or not. In the latter case, this function is called.
+ * Fail to do so will result in block reservation being turned off for that
+ * open file.
+ *
+ * This function is called from ext3_get_blocks_handle(), also called
+ * when setting the reservation window size through ioctl before the file
+ * is open for write (needs block allocation).
+ *
+ * Needs truncate_mutex protection prior to call this function.
+ */
 void ext3_init_block_alloc_info(struct inode *inode)
 {
        struct ext3_inode_info *ei = EXT3_I(inode);
@@ -271,7 +355,7 @@ void ext3_init_block_alloc_info(struct inode *inode)
                rsv->rsv_start = EXT3_RESERVE_WINDOW_NOT_ALLOCATED;
                rsv->rsv_end = EXT3_RESERVE_WINDOW_NOT_ALLOCATED;
 
-               /*
+               /*
                 * if filesystem is mounted with NORESERVATION, the goal
                 * reservation window size is set to zero to indicate
                 * block reservation is off
@@ -287,6 +371,19 @@ void ext3_init_block_alloc_info(struct inode *inode)
        ei->i_block_alloc_info = block_i;
 }
 
+/**
+ * ext3_discard_reservation()
+ * @inode:             inode
+ *
+ * Discard(free) block reservation window on last file close, or truncate
+ * or at last iput().
+ *
+ * It is being called in three cases:
+ *     ext3_release_file(): last writer close the file
+ *     ext3_clear_inode(): last iput(), when nobody link to this file.
+ *     ext3_truncate(): when the block indirect map is about to change.
+ *
+ */
 void ext3_discard_reservation(struct inode *inode)
 {
        struct ext3_inode_info *ei = EXT3_I(inode);
@@ -306,7 +403,14 @@ void ext3_discard_reservation(struct inode *inode)
        }
 }
 
-/* Free given blocks, update quota and i_blocks field */
+/**
+ * ext3_free_blocks_sb() -- Free given blocks and update quota
+ * @handle:                    handle to this transaction
+ * @sb:                                super block
+ * @block:                     start physcial block to free
+ * @count:                     number of blocks to free
+ * @pdquot_freed_blocks:       pointer to quota
+ */
 void ext3_free_blocks_sb(handle_t *handle, struct super_block *sb,
                         ext3_fsblk_t block, unsigned long count,
                         unsigned long *pdquot_freed_blocks)
@@ -419,8 +523,8 @@ do_more:
                }
                /* @@@ This prevents newly-allocated data from being
                 * freed and then reallocated within the same
-                * transaction. 
-                * 
+                * transaction.
+                *
                 * Ideally we would want to allow that to happen, but to
                 * do so requires making journal_forget() capable of
                 * revoking the queued write of a data block, which
@@ -433,7 +537,7 @@ do_more:
                 * safe not to set the allocation bit in the committed
                 * bitmap, because we know that there is no outstanding
                 * activity on the buffer any more and so it is safe to
-                * reallocate it.  
+                * reallocate it.
                 */
                BUFFER_TRACE(bitmap_bh, "set in b_committed_data");
                J_ASSERT_BH(bitmap_bh,
@@ -490,7 +594,13 @@ error_return:
        return;
 }
 
-/* Free given blocks, update quota and i_blocks field */
+/**
+ * ext3_free_blocks() -- Free given blocks and update quota
+ * @handle:            handle for this transaction
+ * @inode:             inode
+ * @block:             start physical block to free
+ * @count:             number of blocks to count
+ */
 void ext3_free_blocks(handle_t *handle, struct inode *inode,
                        ext3_fsblk_t block, unsigned long count)
 {
@@ -508,7 +618,11 @@ void ext3_free_blocks(handle_t *handle, struct inode *inode,
        return;
 }
 
-/*
+/**
+ * ext3_test_allocatable()
+ * @nr:                        given allocation block group
+ * @bh:                        bufferhead contains the bitmap of the given block group
+ *
  * For ext3 allocations, we must not reuse any blocks which are
  * allocated in the bitmap buffer's "last committed data" copy.  This
  * prevents deletes from freeing up the page for reuse until we have
@@ -518,7 +632,7 @@ void ext3_free_blocks(handle_t *handle, struct inode *inode,
  * data would allow the old block to be overwritten before the
  * transaction committed (because we force data to disk before commit).
  * This would lead to corruption if we crashed between overwriting the
- * data and committing the delete. 
+ * data and committing the delete.
  *
  * @@@ We may want to make this allocation behaviour conditional on
  * data-writes at some point, and disable it for metadata allocations or
@@ -541,6 +655,16 @@ static int ext3_test_allocatable(ext3_grpblk_t nr, struct buffer_head *bh)
        return ret;
 }
 
+/**
+ * bitmap_search_next_usable_block()
+ * @start:             the starting block (group relative) of the search
+ * @bh:                        bufferhead contains the block group bitmap
+ * @maxblocks:         the ending block (group relative) of the reservation
+ *
+ * The bitmap search --- search forward alternately through the actual
+ * bitmap on disk and the last-committed copy in journal, until we find a
+ * bit free in both bitmaps.
+ */
 static ext3_grpblk_t
 bitmap_search_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
                                        ext3_grpblk_t maxblocks)
@@ -548,11 +672,6 @@ bitmap_search_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
        ext3_grpblk_t next;
        struct journal_head *jh = bh2jh(bh);
 
-       /*
-        * The bitmap search --- search forward alternately through the actual
-        * bitmap and the last-committed copy until we find a bit free in
-        * both
-        */
        while (start < maxblocks) {
                next = ext3_find_next_zero_bit(bh->b_data, maxblocks, start);
                if (next >= maxblocks)
@@ -562,14 +681,20 @@ bitmap_search_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
                jbd_lock_bh_state(bh);
                if (jh->b_committed_data)
                        start = ext3_find_next_zero_bit(jh->b_committed_data,
-                                                       maxblocks, next);
+                                                       maxblocks, next);
                jbd_unlock_bh_state(bh);
        }
        return -1;
 }
 
-/*
- * Find an allocatable block in a bitmap.  We honour both the bitmap and
+/**
+ * find_next_usable_block()
+ * @start:             the starting block (group relative) to find next
+ *                     allocatable block in bitmap.
+ * @bh:                        bufferhead contains the block group bitmap
+ * @maxblocks:         the ending block (group relative) for the search
+ *
+ * Find an allocatable block in a bitmap.  We honor both the bitmap and
  * its last-committed copy (if that exists), and perform the "most
  * appropriate allocation" algorithm of looking for a free block near
  * the initial goal; then for a free byte somewhere in the bitmap; then
@@ -584,7 +709,7 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
 
        if (start > 0) {
                /*
-                * The goal was occupied; search forward for a free 
+                * The goal was occupied; search forward for a free
                 * block within the next XX blocks.
                 *
                 * end_goal is more or less random, but it has to be
@@ -620,7 +745,11 @@ find_next_usable_block(ext3_grpblk_t start, struct buffer_head *bh,
        return here;
 }
 
-/*
+/**
+ * claim_block()
+ * @block:             the free block (group relative) to allocate
+ * @bh:                        the bufferhead containts the block group bitmap
+ *
  * We think we can allocate this block in this bitmap.  Try to set the bit.
  * If that succeeds then check that nobody has allocated and then freed the
  * block since we saw that is was not marked in b_committed_data.  If it _was_
@@ -646,7 +775,26 @@ claim_block(spinlock_t *lock, ext3_grpblk_t block, struct buffer_head *bh)
        return ret;
 }
 
-/*
+/**
+ * ext3_try_to_allocate()
+ * @sb:                        superblock
+ * @handle:            handle to this transaction
+ * @group:             given allocation block group
+ * @bitmap_bh:         bufferhead holds the block bitmap
+ * @grp_goal:          given target block within the group
+ * @count:             target number of blocks to allocate
+ * @my_rsv:            reservation window
+ *
+ * Attempt to allocate blocks within a give range. Set the range of allocation
+ * first, then find the first free bit(s) from the bitmap (within the range),
+ * and at last, allocate the blocks by claiming the found free bit as allocated.
+ *
+ * To set the range of this allocation:
+ *     if there is a reservation window, only try to allocate block(s) from the
+ *     file's own reservation window;
+ *     Otherwise, the allocation range starts from the give goal block, ends at
+ *     the block group's last block.
+ *
  * If we failed to allocate the desired block then we may end up crossing to a
  * new bitmap.  In that case we must release write access to the old one via
  * ext3_journal_release_buffer(), else we'll run out of credits.
@@ -703,7 +851,8 @@ repeat:
        }
        start = grp_goal;
 
-       if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group), grp_goal, bitmap_bh)) {
+       if (!claim_block(sb_bgl_lock(EXT3_SB(sb), group),
+               grp_goal, bitmap_bh)) {
                /*
                 * The block was allocated by another thread, or it was
                 * allocated and then freed by another thread
@@ -718,7 +867,8 @@ repeat:
        grp_goal++;
        while (num < *count && grp_goal < end
                && ext3_test_allocatable(grp_goal, bitmap_bh)
-               && claim_block(sb_bgl_lock(EXT3_SB(sb), group), grp_goal, bitmap_bh)) {
+               && claim_block(sb_bgl_lock(EXT3_SB(sb), group),
+                               grp_goal, bitmap_bh)) {
                num++;
                grp_goal++;
        }
@@ -730,12 +880,12 @@ fail_access:
 }
 
 /**
- *     find_next_reservable_window():
+ *     find_next_reservable_window():
  *             find a reservable space within the given range.
  *             It does not allocate the reservation window for now:
  *             alloc_new_reservation() will do the work later.
  *
- *     @search_head: the head of the searching list;
+ *     @search_head: the head of the searching list;
  *             This is not necessarily the list head of the whole filesystem
  *
  *             We have both head and start_block to assist the search
@@ -743,12 +893,12 @@ fail_access:
  *             but we will shift to the place where start_block is,
  *             then start from there, when looking for a reservable space.
  *
- *     @size: the target new reservation window size
+ *     @size: the target new reservation window size
  *
- *     @group_first_block: the first block we consider to start
+ *     @group_first_block: the first block we consider to start
  *                     the real search from
  *
- *     @last_block:
+ *     @last_block:
  *             the maximum block number that our goal reservable space
  *             could start from. This is normally the last block in this
  *             group. The search will end when we found the start of next
@@ -756,10 +906,10 @@ fail_access:
  *             This could handle the cross boundary reservation window
  *             request.
  *
- *     basically we search from the given range, rather than the whole
- *     reservation double linked list, (start_block, last_block)
- *     to find a free region that is of my size and has not
- *     been reserved.
+ *     basically we search from the given range, rather than the whole
+ *     reservation double linked list, (start_block, last_block)
+ *     to find a free region that is of my size and has not
+ *     been reserved.
  *
  */
 static int find_next_reservable_window(
@@ -812,7 +962,7 @@ static int find_next_reservable_window(
                        /*
                         * Found a reserveable space big enough.  We could
                         * have a reservation across the group boundary here
-                        */
+                        */
                        break;
                }
        }
@@ -848,7 +998,7 @@ static int find_next_reservable_window(
 }
 
 /**
- *     alloc_new_reservation()--allocate a new reservation window
+ *     alloc_new_reservation()--allocate a new reservation window
  *
  *             To make a new reservation, we search part of the filesystem
  *             reservation list (the list that inside the group). We try to
@@ -897,7 +1047,7 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
        spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock;
 
        group_first_block = ext3_group_first_block_no(sb, group);
-       group_end_block = group_first_block + EXT3_BLOCKS_PER_GROUP(sb) - 1;
+       group_end_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1);
 
        if (grp_goal < 0)
                start_block = group_first_block;
@@ -929,9 +1079,10 @@ static int alloc_new_reservation(struct ext3_reserve_window_node *my_rsv,
                if ((my_rsv->rsv_alloc_hit >
                     (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) {
                        /*
-                        * if we previously allocation hit ration is greater than half
-                        * we double the size of reservation window next time
-                        * otherwise keep the same
+                        * if the previously allocation hit ratio is
+                        * greater than 1/2, then we double the size of
+                        * the reservation window the next time,
+                        * otherwise we keep the same size window
                         */
                        size = size * 2;
                        if (size > EXT3_MAX_RESERVE_BLOCKS)
@@ -1010,6 +1161,23 @@ retry:
        goto retry;
 }
 
+/**
+ * try_to_extend_reservation()
+ * @my_rsv:            given reservation window
+ * @sb:                        super block
+ * @size:              the delta to extend
+ *
+ * Attempt to expand the reservation window large enough to have
+ * required number of free blocks
+ *
+ * Since ext3_try_to_allocate() will always allocate blocks within
+ * the reservation window range, if the window size is too small,
+ * multiple blocks allocation has to stop at the end of the reservation
+ * window. To make this more efficient, given the total number of
+ * blocks needed and the current size of the window, we try to
+ * expand the reservation window size if necessary on a best-effort
+ * basis before ext3_new_blocks() tries to allocate blocks,
+ */
 static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
                        struct super_block *sb, int size)
 {
@@ -1035,7 +1203,17 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
        spin_unlock(rsv_lock);
 }
 
-/*
+/**
+ * ext3_try_to_allocate_with_rsv()
+ * @sb:                        superblock
+ * @handle:            handle to this transaction
+ * @group:             given allocation block group
+ * @bitmap_bh:         bufferhead holds the block bitmap
+ * @grp_goal:          given target block within the group
+ * @count:             target number of blocks to allocate
+ * @my_rsv:            reservation window
+ * @errp:              pointer to store the error code
+ *
  * This is the main function used to allocate a new block and its reservation
  * window.
  *
@@ -1051,9 +1229,7 @@ static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
  * reservation), and there are lots of free blocks, but they are all
  * being reserved.
  *
- * We use a sorted double linked list for the per-filesystem reservation list.
- * The insert, remove and find a free space(non-reserved) operations for the
- * sorted double linked list should be fast.
+ * We use a red-black tree for the per-filesystem reservation list.
  *
  */
 static ext3_grpblk_t
@@ -1063,7 +1239,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
                        struct ext3_reserve_window_node * my_rsv,
                        unsigned long *count, int *errp)
 {
-       ext3_fsblk_t group_first_block;
+       ext3_fsblk_t group_first_block, group_last_block;
        ext3_grpblk_t ret = 0;
        int fatal;
        unsigned long num = *count;
@@ -1100,6 +1276,7 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
         * first block is the block number of the first block in this group
         */
        group_first_block = ext3_group_first_block_no(sb, group);
+       group_last_block = group_first_block + (EXT3_BLOCKS_PER_GROUP(sb) - 1);
 
        /*
         * Basically we will allocate a new block from inode's reservation
@@ -1118,7 +1295,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
         */
        while (1) {
                if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) ||
-                       !goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb)) {
+                       !goal_in_my_reservation(&my_rsv->rsv_window,
+                                               grp_goal, group, sb)) {
                        if (my_rsv->rsv_goal_size < *count)
                                my_rsv->rsv_goal_size = *count;
                        ret = alloc_new_reservation(my_rsv, grp_goal, sb,
@@ -1126,17 +1304,21 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
                        if (ret < 0)
                                break;                  /* failed */
 
-                       if (!goal_in_my_reservation(&my_rsv->rsv_window, grp_goal, group, sb))
+                       if (!goal_in_my_reservation(&my_rsv->rsv_window,
+                                                       grp_goal, group, sb))
                                grp_goal = -1;
-               } else if (grp_goal > 0 && (my_rsv->rsv_end-grp_goal+1) < *count)
+               } else if (grp_goal > 0 &&
+                         (my_rsv->rsv_end-grp_goal+1) < *count)
                        try_to_extend_reservation(my_rsv, sb,
                                        *count-my_rsv->rsv_end + grp_goal - 1);
 
-               if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb))
-                   || (my_rsv->rsv_end < group_first_block))
+               if ((my_rsv->rsv_start > group_last_block) ||
+                               (my_rsv->rsv_end < group_first_block)) {
+                       rsv_window_dump(&EXT3_SB(sb)->s_rsv_window_root, 1);
                        BUG();
-               ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, grp_goal,
-                                          &num, &my_rsv->rsv_window);
+               }
+               ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh,
+                                          grp_goal, &num, &my_rsv->rsv_window);
                if (ret >= 0) {
                        my_rsv->rsv_alloc_hit += num;
                        *count = num;
@@ -1161,6 +1343,12 @@ out:
        return ret;
 }
 
+/**
+ * ext3_has_free_blocks()
+ * @sbi:               in-core super block structure.
+ *
+ * Check if filesystem has at least 1 free block available for allocation.
+ */
 static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
 {
        ext3_fsblk_t free_blocks, root_blocks;
@@ -1175,11 +1363,17 @@ static int ext3_has_free_blocks(struct ext3_sb_info *sbi)
        return 1;
 }
 
-/*
+/**
+ * ext3_should_retry_alloc()
+ * @sb:                        super block
+ * @retries            number of attemps has been made
+ *
  * ext3_should_retry_alloc() is called when ENOSPC is returned, and if
  * it is profitable to retry the operation, this function will wait
  * for the current or commiting transaction to complete, and then
  * return TRUE.
+ *
+ * if the total number of retries exceed three times, return FALSE.
  */
 int ext3_should_retry_alloc(struct super_block *sb, int *retries)
 {
@@ -1191,13 +1385,19 @@ int ext3_should_retry_alloc(struct super_block *sb, int *retries)
        return journal_force_commit_nested(EXT3_SB(sb)->s_journal);
 }
 
-/*
- * ext3_new_block uses a goal block to assist allocation.  If the goal is
- * free, or there is a free block within 32 blocks of the goal, that block
- * is allocated.  Otherwise a forward search is made for a free block; within 
- * each block group the search first looks for an entire free byte in the block
- * bitmap, and then for any free bit if that fails.
- * This function also updates quota and i_blocks field.
+/**
+ * ext3_new_blocks() -- core block(s) allocation function
+ * @handle:            handle to this transaction
+ * @inode:             file inode
+ * @goal:              given target block(filesystem wide)
+ * @count:             target number of blocks to allocate
+ * @errp:              error code
+ *
+ * ext3_new_blocks uses a goal block to assist allocation.  It tries to
+ * allocate block(s) from the block group contains the goal block first. If that
+ * fails, it will try to allocate block(s) from other block groups without
+ * any specific goal block.
+ *
  */
 ext3_fsblk_t ext3_new_blocks(handle_t *handle, struct inode *inode,
                        ext3_fsblk_t goal, unsigned long *count, int *errp)
@@ -1303,7 +1503,7 @@ retry_alloc:
        smp_rmb();
 
        /*
-        * Now search the rest of the groups.  We assume that 
+        * Now search the rest of the groups.  We assume that
         * i and gdp correctly point to the last group visited.
         */
        for (bgi = 0; bgi < ngroups; bgi++) {
@@ -1428,7 +1628,7 @@ allocated:
 
        spin_lock(sb_bgl_lock(sbi, group_no));
        gdp->bg_free_blocks_count =
-                       cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - num);
+                       cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)-num);
        spin_unlock(sb_bgl_lock(sbi, group_no));
        percpu_counter_mod(&sbi->s_freeblocks_counter, -num);
 
@@ -1471,6 +1671,12 @@ ext3_fsblk_t ext3_new_block(handle_t *handle, struct inode *inode,
        return ext3_new_blocks(handle, inode, goal, &count, errp);
 }
 
+/**
+ * ext3_count_free_blocks() -- count filesystem free blocks
+ * @sb:                superblock
+ *
+ * Adds up the number of free blocks from each block group.
+ */
 ext3_fsblk_t ext3_count_free_blocks(struct super_block *sb)
 {
        ext3_fsblk_t desc_count;
index ce4f82b9e528d6dd6a64045144f34792611bf764..b9176eed98d1258518bd9cebfbbdb071baa458fc 100644 (file)
@@ -20,7 +20,7 @@ unsigned long ext3_count_free (struct buffer_head * map, unsigned int numchars)
        unsigned int i;
        unsigned long sum = 0;
 
-       if (!map) 
+       if (!map)
                return (0);
        for (i = 0; i < numchars; i++)
                sum += nibblemap[map->b_data[i] & 0xf] +
index fbb0d4ed07d4322e947f081f1af4dd6fd025ce33..429acbb4e064bd21352f8019e133a781523169fb 100644 (file)
@@ -59,7 +59,7 @@ static unsigned char get_dtype(struct super_block *sb, int filetype)
 
        return (ext3_filetype_table[filetype]);
 }
-                              
+
 
 int ext3_check_dir_entry (const char * function, struct inode * dir,
                          struct ext3_dir_entry_2 * de,
@@ -67,7 +67,7 @@ int ext3_check_dir_entry (const char * function, struct inode * dir,
                          unsigned long offset)
 {
        const char * error_msg = NULL;
-       const int rlen = le16_to_cpu(de->rec_len);
+       const int rlen = le16_to_cpu(de->rec_len);
 
        if (rlen < EXT3_DIR_REC_LEN(1))
                error_msg = "rec_len is smaller than minimal";
@@ -162,7 +162,7 @@ revalidate:
                 * to make sure. */
                if (filp->f_version != inode->i_version) {
                        for (i = 0; i < sb->s_blocksize && i < offset; ) {
-                               de = (struct ext3_dir_entry_2 *) 
+                               de = (struct ext3_dir_entry_2 *)
                                        (bh->b_data + i);
                                /* It's too expensive to do a full
                                 * dirent test each time round this
@@ -181,7 +181,7 @@ revalidate:
                        filp->f_version = inode->i_version;
                }
 
-               while (!error && filp->f_pos < inode->i_size 
+               while (!error && filp->f_pos < inode->i_size
                       && offset < sb->s_blocksize) {
                        de = (struct ext3_dir_entry_2 *) (bh->b_data + offset);
                        if (!ext3_check_dir_entry ("ext3_readdir", inode, de,
@@ -229,7 +229,7 @@ out:
 /*
  * These functions convert from the major/minor hash to an f_pos
  * value.
- * 
+ *
  * Currently we only use major hash numer.  This is unfortunate, but
  * on 32-bit machines, the same VFS interface is used for lseek and
  * llseek, so if we use the 64 bit offset, then the 32-bit versions of
@@ -250,7 +250,7 @@ out:
 struct fname {
        __u32           hash;
        __u32           minor_hash;
-       struct rb_node  rb_hash; 
+       struct rb_node  rb_hash;
        struct fname    *next;
        __u32           inode;
        __u8            name_len;
@@ -343,10 +343,9 @@ int ext3_htree_store_dirent(struct file *dir_file, __u32 hash,
 
        /* Create and allocate the fname structure */
        len = sizeof(struct fname) + dirent->name_len + 1;
-       new_fn = kmalloc(len, GFP_KERNEL);
+       new_fn = kzalloc(len, GFP_KERNEL);
        if (!new_fn)
                return -ENOMEM;
-       memset(new_fn, 0, len);
        new_fn->hash = hash;
        new_fn->minor_hash = minor_hash;
        new_fn->inode = le32_to_cpu(dirent->inode);
@@ -410,7 +409,7 @@ static int call_filldir(struct file * filp, void * dirent,
        curr_pos = hash2pos(fname->hash, fname->minor_hash);
        while (fname) {
                error = filldir(dirent, fname->name,
-                               fname->name_len, curr_pos, 
+                               fname->name_len, curr_pos,
                                fname->inode,
                                get_dtype(sb, fname->file_type));
                if (error) {
@@ -465,7 +464,7 @@ static int ext3_dx_readdir(struct file * filp,
                /*
                 * Fill the rbtree if we have no more entries,
                 * or the inode has changed since we last read in the
-                * cached entries. 
+                * cached entries.
                 */
                if ((!info->curr_node) ||
                    (filp->f_version != inode->i_version)) {
index 1efefb630ea971dae9728b32ac8beace5ad79187..994efd189f4e3c7bd667e866d359670189f7ea65 100644 (file)
@@ -100,7 +100,7 @@ ext3_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
 
 force_commit:
        err = ext3_force_commit(inode->i_sb);
-       if (err) 
+       if (err)
                return err;
        return ret;
 }
index 49382a208e05e3fdd1bf62e8f9495a46a614e587..dd1fd3c0fc05c1bf4593decf9cd692df28558079 100644 (file)
@@ -8,14 +8,14 @@
  *                      Universite Pierre et Marie Curie (Paris VI)
  *  from
  *  linux/fs/minix/truncate.c   Copyright (C) 1991, 1992  Linus Torvalds
- * 
+ *
  *  ext3fs fsync primitive
  *
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
- * 
+ *
  *  Removed unnecessary code duplication for little endian machines
- *  and excessive __inline__s. 
+ *  and excessive __inline__s.
  *        Andi Kleen, 1997
  *
  * Major simplications and cleanup - we only need to do the metadata, because
index 5a2d1235ead01562b5ca04988ed12a2a92ea86dd..deeb27b5ba833d25009c33c3c31752fec8d79dd3 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2002 by Theodore Ts'o
  *
  * This file is released under the GPL v2.
- * 
+ *
  * This file may be redistributed under the terms of the GNU Public
  * License.
  */
@@ -80,11 +80,11 @@ static void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
  * Returns the hash of a filename.  If len is 0 and name is NULL, then
  * this function can be used to test whether or not a hash version is
  * supported.
- * 
+ *
  * The seed is an 4 longword (32 bits) "secret" which can be used to
  * uniquify a hash.  If the seed is all zero's, then some default seed
  * may be used.
- * 
+ *
  * A particular hash version specifies whether or not the seed is
  * represented, and whether or not the returned hash is 32 bits or 64
  * bits.  32 bit hashes will return 0 for the minor hash.
@@ -95,7 +95,7 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo)
        __u32   minor_hash = 0;
        const char      *p;
        int             i;
-       __u32           in[8], buf[4];
+       __u32           in[8], buf[4];
 
        /* Initialize the default seed for the hash checksum functions */
        buf[0] = 0x67452301;
index 36546ed36a1476df87adf736bcab38a9dbcac822..e45dbd65173624c10796655baa0566c98ece4f29 100644 (file)
@@ -202,7 +202,7 @@ error_return:
 static int find_group_dir(struct super_block *sb, struct inode *parent)
 {
        int ngroups = EXT3_SB(sb)->s_groups_count;
-       int freei, avefreei;
+       unsigned int freei, avefreei;
        struct ext3_group_desc *desc, *best_desc = NULL;
        struct buffer_head *bh;
        int group, best_group = -1;
@@ -216,7 +216,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
                        continue;
                if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
                        continue;
-               if (!best_desc || 
+               if (!best_desc ||
                    (le16_to_cpu(desc->bg_free_blocks_count) >
                     le16_to_cpu(best_desc->bg_free_blocks_count))) {
                        best_group = group;
@@ -226,30 +226,30 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)
        return best_group;
 }
 
-/* 
- * Orlov's allocator for directories. 
- * 
+/*
+ * Orlov's allocator for directories.
+ *
  * We always try to spread first-level directories.
  *
- * If there are blockgroups with both free inodes and free blocks counts 
- * not worse than average we return one with smallest directory count. 
- * Otherwise we simply return a random group. 
- * 
- * For the rest rules look so: 
- * 
- * It's OK to put directory into a group unless 
- * it has too many directories already (max_dirs) or 
- * it has too few free inodes left (min_inodes) or 
- * it has too few free blocks left (min_blocks) or 
- * it's already running too large debt (max_debt). 
- * Parent's group is prefered, if it doesn't satisfy these 
- * conditions we search cyclically through the rest. If none 
- * of the groups look good we just look for a group with more 
- * free inodes than average (starting at parent's group). 
- * 
- * Debt is incremented each time we allocate a directory and decremented 
- * when we allocate an inode, within 0--255. 
- */ 
+ * If there are blockgroups with both free inodes and free blocks counts
+ * not worse than average we return one with smallest directory count.
+ * Otherwise we simply return a random group.
+ *
+ * For the rest rules look so:
+ *
+ * It's OK to put directory into a group unless
+ * it has too many directories already (max_dirs) or
+ * it has too few free inodes left (min_inodes) or
+ * it has too few free blocks left (min_blocks) or
+ * it's already running too large debt (max_debt).
+ * Parent's group is prefered, if it doesn't satisfy these
+ * conditions we search cyclically through the rest. If none
+ * of the groups look good we just look for a group with more
+ * free inodes than average (starting at parent's group).
+ *
+ * Debt is incremented each time we allocate a directory and decremented
+ * when we allocate an inode, within 0--255.
+ */
 
 #define INODE_COST 64
 #define BLOCK_COST 256
@@ -261,10 +261,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)
        struct ext3_super_block *es = sbi->s_es;
        int ngroups = sbi->s_groups_count;
        int inodes_per_group = EXT3_INODES_PER_GROUP(sb);
-       int freei, avefreei;
+       unsigned int freei, avefreei;
        ext3_fsblk_t freeb, avefreeb;
        ext3_fsblk_t blocks_per_dir;
-       int ndirs;
+       unsigned int ndirs;
        int max_debt, max_dirs, min_inodes;
        ext3_grpblk_t min_blocks;
        int group = -1, i;
@@ -454,7 +454,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)
                        group = find_group_dir(sb, dir);
                else
                        group = find_group_orlov(sb, dir);
-       } else 
+       } else
                group = find_group_other(sb, dir);
 
        err = -ENOSPC;
@@ -559,7 +559,6 @@ got:
 
        inode->i_ino = ino;
        /* This is the optimal IO size (for stat), not the fs block size */
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
 
index 84be02e93652bd8e5548d8f07ad6e57c5947c817..dcf4f1dd108b21acd60c4ea3c88b0d8780b319c3 100644 (file)
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  *  Goal-directed block allocation by Stephen Tweedie
- *     (sct@redhat.com), 1993, 1998
+ *     (sct@redhat.com), 1993, 1998
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  *  64-bit file support on 64-bit platforms by Jakub Jelinek
- *     (jj@sunsite.ms.mff.cuni.cz)
+ *     (jj@sunsite.ms.mff.cuni.cz)
  *
  *  Assorted race fixes, rewrite of ext3_get_block() by Al Viro, 2000
  */
@@ -55,7 +55,7 @@ static int ext3_inode_is_fast_symlink(struct inode *inode)
 /*
  * The ext3 forget function must perform a revoke if we are freeing data
  * which has been journaled.  Metadata (eg. indirect blocks) must be
- * revoked in all cases. 
+ * revoked in all cases.
  *
  * "bh" may be NULL: a metadata block may have been freed from memory
  * but there may still be a record of it in the journal, and that record
@@ -105,7 +105,7 @@ int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode,
  * Work out how many blocks we need to proceed with the next chunk of a
  * truncate transaction.
  */
-static unsigned long blocks_for_truncate(struct inode *inode) 
+static unsigned long blocks_for_truncate(struct inode *inode)
 {
        unsigned long needed;
 
@@ -122,13 +122,13 @@ static unsigned long blocks_for_truncate(struct inode *inode)
 
        /* But we need to bound the transaction so we don't overflow the
         * journal. */
-       if (needed > EXT3_MAX_TRANS_DATA) 
+       if (needed > EXT3_MAX_TRANS_DATA)
                needed = EXT3_MAX_TRANS_DATA;
 
        return EXT3_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
 }
 
-/* 
+/*
  * Truncate transactions can be complex and absolutely huge.  So we need to
  * be able to restart the transaction at a conventient checkpoint to make
  * sure we don't overflow the journal.
@@ -136,9 +136,9 @@ static unsigned long blocks_for_truncate(struct inode *inode)
  * start_transaction gets us a new handle for a truncate transaction,
  * and extend_transaction tries to extend the existing one a bit.  If
  * extend fails, we need to propagate the failure up and restart the
- * transaction in the top-level truncate loop. --sct 
+ * transaction in the top-level truncate loop. --sct
  */
-static handle_t *start_transaction(struct inode *inode) 
+static handle_t *start_transaction(struct inode *inode)
 {
        handle_t *result;
 
@@ -215,12 +215,12 @@ void ext3_delete_inode (struct inode * inode)
        ext3_orphan_del(handle, inode);
        EXT3_I(inode)->i_dtime  = get_seconds();
 
-       /* 
+       /*
         * One subtle ordering requirement: if anything has gone wrong
         * (transaction abort, IO errors, whatever), then we can still
         * do these next steps (the fs will already have been marked as
         * having errors), but we can't free the inode if the mark_dirty
-        * fails.  
+        * fails.
         */
        if (ext3_mark_inode_dirty(handle, inode))
                /* If that failed, just do the required in-core inode clear. */
@@ -398,7 +398,7 @@ no_block:
  *       + if there is a block to the left of our position - allocate near it.
  *       + if pointer will live in indirect block - allocate near that block.
  *       + if pointer will live in inode - allocate in the same
- *         cylinder group. 
+ *         cylinder group.
  *
  * In the latter case we colour the starting block by the callers PID to
  * prevent it from clashing with concurrent allocations for a different inode
@@ -470,7 +470,7 @@ static ext3_fsblk_t ext3_find_goal(struct inode *inode, long block,
  *     ext3_blks_to_allocate: Look up the block map and count the number
  *     of direct blocks need to be allocated for the given branch.
  *
- *     @branch: chain of indirect blocks
+ *     @branch: chain of indirect blocks
  *     @k: number of blocks need for indirect blocks
  *     @blks: number of data blocks to be mapped.
  *     @blocks_to_boundary:  the offset in the indirect block
@@ -744,7 +744,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode,
                jbd_debug(5, "splicing indirect only\n");
                BUFFER_TRACE(where->bh, "call ext3_journal_dirty_metadata");
                err = ext3_journal_dirty_metadata(handle, where->bh);
-               if (err) 
+               if (err)
                        goto err_out;
        } else {
                /*
@@ -1098,7 +1098,7 @@ static int walk_page_buffers(     handle_t *handle,
 
        for (   bh = head, block_start = 0;
                ret == 0 && (bh != head || !block_start);
-               block_start = block_end, bh = next)
+               block_start = block_end, bh = next)
        {
                next = bh->b_this_page;
                block_end = block_start + blocksize;
@@ -1137,7 +1137,7 @@ static int walk_page_buffers(     handle_t *handle,
  * So what we do is to rely on the fact that journal_stop/journal_start
  * will _not_ run commit under these circumstances because handle->h_ref
  * is elevated.  We'll still have enough credits for the tiny quotafile
- * write.  
+ * write.
  */
 static int do_journal_get_write_access(handle_t *handle,
                                        struct buffer_head *bh)
@@ -1282,7 +1282,7 @@ static int ext3_journalled_commit_write(struct file *file,
        if (inode->i_size > EXT3_I(inode)->i_disksize) {
                EXT3_I(inode)->i_disksize = inode->i_size;
                ret2 = ext3_mark_inode_dirty(handle, inode);
-               if (!ret) 
+               if (!ret)
                        ret = ret2;
        }
        ret2 = ext3_journal_stop(handle);
@@ -1291,7 +1291,7 @@ static int ext3_journalled_commit_write(struct file *file,
        return ret;
 }
 
-/* 
+/*
  * bmap() is special.  It gets used by applications such as lilo and by
  * the swapper to find the on-disk block of a specific piece of data.
  *
@@ -1300,10 +1300,10 @@ static int ext3_journalled_commit_write(struct file *file,
  * filesystem and enables swap, then they may get a nasty shock when the
  * data getting swapped to that swapfile suddenly gets overwritten by
  * the original zero's written out previously to the journal and
- * awaiting writeback in the kernel's buffer cache. 
+ * awaiting writeback in the kernel's buffer cache.
  *
  * So, if we see any bmap calls here on a modified, data-journaled file,
- * take extra steps to flush any blocks which might be in the cache. 
+ * take extra steps to flush any blocks which might be in the cache.
  */
 static sector_t ext3_bmap(struct address_space *mapping, sector_t block)
 {
@@ -1312,16 +1312,16 @@ static sector_t ext3_bmap(struct address_space *mapping, sector_t block)
        int err;
 
        if (EXT3_I(inode)->i_state & EXT3_STATE_JDATA) {
-               /* 
+               /*
                 * This is a REALLY heavyweight approach, but the use of
                 * bmap on dirty files is expected to be extremely rare:
                 * only if we run lilo or swapon on a freshly made file
-                * do we expect this to happen. 
+                * do we expect this to happen.
                 *
                 * (bmap requires CAP_SYS_RAWIO so this does not
                 * represent an unprivileged user DOS attack --- we'd be
                 * in trouble if mortal users could trigger this path at
-                * will.) 
+                * will.)
                 *
                 * NB. EXT3_STATE_JDATA is not set on files other than
                 * regular files.  If somebody wants to bmap a directory
@@ -1457,7 +1457,7 @@ static int ext3_ordered_writepage(struct page *page,
         */
 
        /*
-        * And attach them to the current transaction.  But only if 
+        * And attach them to the current transaction.  But only if
         * block_write_full_page() succeeded.  Otherwise they are unmapped,
         * and generally junk.
         */
@@ -1644,7 +1644,7 @@ static ssize_t ext3_direct_IO(int rw, struct kiocb *iocb,
                }
        }
 
-       ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, 
+       ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
                                 offset, nr_segs,
                                 ext3_get_block, NULL);
 
@@ -2025,7 +2025,7 @@ static void ext3_free_data(handle_t *handle, struct inode *inode,
                           __le32 *first, __le32 *last)
 {
        ext3_fsblk_t block_to_free = 0;    /* Starting block # of a run */
-       unsigned long count = 0;            /* Number of blocks in the run */ 
+       unsigned long count = 0;            /* Number of blocks in the run */
        __le32 *block_to_free_p = NULL;     /* Pointer into inode/ind
                                               corresponding to
                                               block_to_free */
@@ -2054,7 +2054,7 @@ static void ext3_free_data(handle_t *handle, struct inode *inode,
                        } else if (nr == block_to_free + count) {
                                count++;
                        } else {
-                               ext3_clear_blocks(handle, inode, this_bh, 
+                               ext3_clear_blocks(handle, inode, this_bh,
                                                  block_to_free,
                                                  count, block_to_free_p, p);
                                block_to_free = nr;
@@ -2115,7 +2115,7 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
                         */
                        if (!bh) {
                                ext3_error(inode->i_sb, "ext3_free_branches",
-                                          "Read failure, inode=%ld, block="E3FSBLK,
+                                          "Read failure, inode=%lu, block="E3FSBLK,
                                           inode->i_ino, nr);
                                continue;
                        }
@@ -2184,7 +2184,7 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
                                        *p = 0;
                                        BUFFER_TRACE(parent_bh,
                                        "call ext3_journal_dirty_metadata");
-                                       ext3_journal_dirty_metadata(handle, 
+                                       ext3_journal_dirty_metadata(handle,
                                                                    parent_bh);
                                }
                        }
@@ -2632,9 +2632,6 @@ void ext3_read_inode(struct inode * inode)
                 * recovery code: that's fine, we're about to complete
                 * the process of deleting those. */
        }
-       inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size
-                                        * (for stat), not the fs block
-                                        * size */  
        inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
        ei->i_flags = le32_to_cpu(raw_inode->i_flags);
 #ifdef EXT3_FRAGMENTS
@@ -2704,7 +2701,7 @@ void ext3_read_inode(struct inode * inode)
                if (raw_inode->i_block[0])
                        init_special_inode(inode, inode->i_mode,
                           old_decode_dev(le32_to_cpu(raw_inode->i_block[0])));
-               else 
+               else
                        init_special_inode(inode, inode->i_mode,
                           new_decode_dev(le32_to_cpu(raw_inode->i_block[1])));
        }
@@ -2724,8 +2721,8 @@ bad_inode:
  *
  * The caller must have write access to iloc->bh.
  */
-static int ext3_do_update_inode(handle_t *handle, 
-                               struct inode *inode, 
+static int ext3_do_update_inode(handle_t *handle,
+                               struct inode *inode,
                                struct ext3_iloc *iloc)
 {
        struct ext3_inode *raw_inode = ext3_raw_inode(iloc);
@@ -2900,7 +2897,7 @@ int ext3_write_inode(struct inode *inode, int wait)
  * commit will leave the blocks being flushed in an unused state on
  * disk.  (On recovery, the inode will get truncated and the blocks will
  * be freed, so we have a strong guarantee that no future commit will
- * leave these blocks visible to the user.)  
+ * leave these blocks visible to the user.)
  *
  * Called with inode->sem down.
  */
@@ -3043,13 +3040,13 @@ int ext3_mark_iloc_dirty(handle_t *handle,
        return err;
 }
 
-/* 
+/*
  * On success, We end up with an outstanding reference count against
- * iloc->bh.  This _must_ be cleaned up later. 
+ * iloc->bh.  This _must_ be cleaned up later.
  */
 
 int
-ext3_reserve_inode_write(handle_t *handle, struct inode *inode, 
+ext3_reserve_inode_write(handle_t *handle, struct inode *inode,
                         struct ext3_iloc *iloc)
 {
        int err = 0;
@@ -3139,7 +3136,7 @@ out:
 }
 
 #if 0
-/* 
+/*
  * Bind an inode's backing buffer_head into this transaction, to prevent
  * it from being flushed to disk early.  Unlike
  * ext3_reserve_inode_write, this leaves behind no bh reference and
@@ -3157,7 +3154,7 @@ static int ext3_pin_inode(handle_t *handle, struct inode *inode)
                        BUFFER_TRACE(iloc.bh, "get_write_access");
                        err = journal_get_write_access(handle, iloc.bh);
                        if (!err)
-                               err = ext3_journal_dirty_metadata(handle, 
+                               err = ext3_journal_dirty_metadata(handle,
                                                                  iloc.bh);
                        brelse(iloc.bh);
                }
index 2aa7101b27cd31bda494dbf5d688f1aa469f2985..85d132c37ee0f1a8a8c840432d7839f4d9b97af6 100644 (file)
  *  Big-endian to little-endian byte-swapping/bitmaps by
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  *  Directory entry file type support and forward compatibility hooks
- *     for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
+ *     for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
  *  Hash Tree Directory indexing (c)
- *     Daniel Phillips, 2001
+ *     Daniel Phillips, 2001
  *  Hash Tree Directory indexing porting
- *     Christopher Li, 2002
+ *     Christopher Li, 2002
  *  Hash Tree Directory indexing cleanup
- *     Theodore Ts'o, 2002
+ *     Theodore Ts'o, 2002
  */
 
 #include <linux/fs.h>
@@ -76,7 +76,7 @@ static struct buffer_head *ext3_append(handle_t *handle,
 #ifdef DX_DEBUG
 #define dxtrace(command) command
 #else
-#define dxtrace(command) 
+#define dxtrace(command)
 #endif
 
 struct fake_dirent
@@ -169,7 +169,7 @@ static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size);
 static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
 static int ext3_htree_next_block(struct inode *dir, __u32 hash,
                                 struct dx_frame *frame,
-                                struct dx_frame *frames, 
+                                struct dx_frame *frames,
                                 __u32 *start_hash);
 static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
                       struct ext3_dir_entry_2 **res_dir, int *err);
@@ -250,7 +250,7 @@ static void dx_show_index (char * label, struct dx_entry *entries)
 }
 
 struct stats
-{ 
+{
        unsigned names;
        unsigned space;
        unsigned bcount;
@@ -278,7 +278,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_ent
                                       ((char *) de - base));
                        }
                        space += EXT3_DIR_REC_LEN(de->name_len);
-                       names++;
+                       names++;
                }
                de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len));
        }
@@ -464,7 +464,7 @@ static void dx_release (struct dx_frame *frames)
  */
 static int ext3_htree_next_block(struct inode *dir, __u32 hash,
                                 struct dx_frame *frame,
-                                struct dx_frame *frames, 
+                                struct dx_frame *frames,
                                 __u32 *start_hash)
 {
        struct dx_frame *p;
@@ -632,7 +632,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
                }
                count += ret;
                hashval = ~0;
-               ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, 
+               ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS,
                                            frame, frames, &hashval);
                *next_hash = hashval;
                if (ret < 0) {
@@ -649,7 +649,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash,
                        break;
        }
        dx_release(frames);
-       dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n", 
+       dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n",
                       count, *next_hash));
        return count;
 errout:
@@ -1050,7 +1050,7 @@ struct dentry *ext3_get_parent(struct dentry *child)
                parent = ERR_PTR(-ENOMEM);
        }
        return parent;
-} 
+}
 
 #define S_SHIFT 12
 static unsigned char ext3_type_by_mode[S_IFMT >> S_SHIFT] = {
@@ -1198,7 +1198,7 @@ errout:
  * add_dirent_to_buf will attempt search the directory block for
  * space.  It will return -ENOSPC if no space is available, and -EIO
  * and -EEXIST if directory entry already exists.
- * 
+ *
  * NOTE!  bh is NOT released in the case where ENOSPC is returned.  In
  * all other cases bh is released.
  */
@@ -1572,7 +1572,7 @@ cleanup:
  * ext3_delete_entry deletes a directory entry by merging it with the
  * previous entry
  */
-static int ext3_delete_entry (handle_t *handle, 
+static int ext3_delete_entry (handle_t *handle,
                              struct inode * dir,
                              struct ext3_dir_entry_2 * de_del,
                              struct buffer_head * bh)
@@ -1643,12 +1643,12 @@ static int ext3_add_nondir(handle_t *handle,
  * is so far negative - it has no inode.
  *
  * If the create succeeds, we fill in the inode information
- * with d_instantiate(). 
+ * with d_instantiate().
  */
 static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
                struct nameidata *nd)
 {
-       handle_t *handle; 
+       handle_t *handle;
        struct inode * inode;
        int err, retries = 0;
 
@@ -1688,7 +1688,7 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
 
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
-                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
+                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
                                        2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
@@ -1813,10 +1813,10 @@ static int empty_dir (struct inode * inode)
        de1 = (struct ext3_dir_entry_2 *)
                        ((char *) de + le16_to_cpu(de->rec_len));
        if (le32_to_cpu(de->inode) != inode->i_ino ||
-                       !le32_to_cpu(de1->inode) || 
+                       !le32_to_cpu(de1->inode) ||
                        strcmp (".", de->name) ||
                        strcmp ("..", de1->name)) {
-               ext3_warning (inode->i_sb, "empty_dir",
+               ext3_warning (inode->i_sb, "empty_dir",
                              "bad directory (dir #%lu) - no `.' or `..'",
                              inode->i_ino);
                brelse (bh);
@@ -1883,7 +1883,7 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode)
         * being truncated, or files being unlinked. */
 
        /* @@@ FIXME: Observation from aviro:
-        * I think I can trigger J_ASSERT in ext3_orphan_add().  We block 
+        * I think I can trigger J_ASSERT in ext3_orphan_add().  We block
         * here (on lock_super()), so race with ext3_link() which might bump
         * ->i_nlink. For, say it, character device. Not a regular file,
         * not a directory, not a symlink and ->i_nlink > 0.
@@ -1919,8 +1919,8 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode)
        if (!err)
                list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan);
 
-       jbd_debug(4, "superblock will point to %ld\n", inode->i_ino);
-       jbd_debug(4, "orphan inode %ld will point to %d\n",
+       jbd_debug(4, "superblock will point to %lu\n", inode->i_ino);
+       jbd_debug(4, "orphan inode %lu will point to %d\n",
                        inode->i_ino, NEXT_ORPHAN(inode));
 out_unlock:
        unlock_super(sb);
@@ -2129,7 +2129,7 @@ static int ext3_symlink (struct inode * dir,
 
 retry:
        handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
-                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
+                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
                                        2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
        if (IS_ERR(handle))
                return PTR_ERR(handle);
@@ -2227,7 +2227,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
                DQUOT_INIT(new_dentry->d_inode);
        handle = ext3_journal_start(old_dir, 2 *
                                        EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) +
-                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
+                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
        if (IS_ERR(handle))
                return PTR_ERR(handle);
 
@@ -2393,4 +2393,4 @@ struct inode_operations ext3_special_inode_operations = {
        .removexattr    = generic_removexattr,
 #endif
        .permission     = ext3_permission,
-}; 
+};
index 5e1337fd878a93c4bbd079e3daea0bf3c2d8ec3d..b73cba12f79c0512cb62362a3d5181217b184e22 100644 (file)
@@ -336,7 +336,7 @@ static int verify_reserved_gdb(struct super_block *sb,
        unsigned five = 5;
        unsigned seven = 7;
        unsigned grp;
-       __u32 *p = (__u32 *)primary->b_data;
+       __le32 *p = (__le32 *)primary->b_data;
        int gdbackups = 0;
 
        while ((grp = ext3_list_backups(sb, &three, &five, &seven)) < end) {
@@ -380,7 +380,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        struct buffer_head *dind;
        int gdbackups;
        struct ext3_iloc iloc;
-       __u32 *data;
+       __le32 *data;
        int err;
 
        if (test_opt(sb, DEBUG))
@@ -417,7 +417,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
                goto exit_bh;
        }
 
-       data = (__u32 *)dind->b_data;
+       data = (__le32 *)dind->b_data;
        if (le32_to_cpu(data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)]) != gdblock) {
                ext3_warning(sb, __FUNCTION__,
                             "new group %u GDT block "E3FSBLK" not reserved",
@@ -439,8 +439,8 @@ static int add_new_gdb(handle_t *handle, struct inode *inode,
        if ((err = ext3_reserve_inode_write(handle, inode, &iloc)))
                goto exit_dindj;
 
-       n_group_desc = (struct buffer_head **)kmalloc((gdb_num + 1) *
-                               sizeof(struct buffer_head *), GFP_KERNEL);
+       n_group_desc = kmalloc((gdb_num + 1) * sizeof(struct buffer_head *),
+                       GFP_KERNEL);
        if (!n_group_desc) {
                err = -ENOMEM;
                ext3_warning (sb, __FUNCTION__,
@@ -519,7 +519,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
        struct buffer_head *dind;
        struct ext3_iloc iloc;
        ext3_fsblk_t blk;
-       __u32 *data, *end;
+       __le32 *data, *end;
        int gdbackups = 0;
        int res, i;
        int err;
@@ -536,8 +536,8 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
        }
 
        blk = EXT3_SB(sb)->s_sbh->b_blocknr + 1 + EXT3_SB(sb)->s_gdb_count;
-       data = (__u32 *)dind->b_data + EXT3_SB(sb)->s_gdb_count;
-       end = (__u32 *)dind->b_data + EXT3_ADDR_PER_BLOCK(sb);
+       data = (__le32 *)dind->b_data + EXT3_SB(sb)->s_gdb_count;
+       end = (__le32 *)dind->b_data + EXT3_ADDR_PER_BLOCK(sb);
 
        /* Get each reserved primary GDT block and verify it holds backups */
        for (res = 0; res < reserved_gdb; res++, blk++) {
@@ -545,7 +545,8 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
                        ext3_warning(sb, __FUNCTION__,
                                     "reserved block "E3FSBLK
                                     " not at offset %ld",
-                                    blk, (long)(data - (__u32 *)dind->b_data));
+                                    blk,
+                                    (long)(data - (__le32 *)dind->b_data));
                        err = -EINVAL;
                        goto exit_bh;
                }
@@ -560,7 +561,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
                        goto exit_bh;
                }
                if (++data >= end)
-                       data = (__u32 *)dind->b_data;
+                       data = (__le32 *)dind->b_data;
        }
 
        for (i = 0; i < reserved_gdb; i++) {
@@ -584,7 +585,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
        blk = input->group * EXT3_BLOCKS_PER_GROUP(sb);
        for (i = 0; i < reserved_gdb; i++) {
                int err2;
-               data = (__u32 *)primary[i]->b_data;
+               data = (__le32 *)primary[i]->b_data;
                /* printk("reserving backup %lu[%u] = %lu\n",
                       primary[i]->b_blocknr, gdbackups,
                       blk + primary[i]->b_blocknr); */
@@ -689,7 +690,7 @@ exit_err:
                             "can't update backup for group %d (err %d), "
                             "forcing fsck on next reboot", group, err);
                sbi->s_mount_state &= ~EXT3_VALID_FS;
-               sbi->s_es->s_state &= ~cpu_to_le16(EXT3_VALID_FS);
+               sbi->s_es->s_state &= cpu_to_le16(~EXT3_VALID_FS);
                mark_buffer_dirty(sbi->s_sbh);
        }
 }
@@ -730,6 +731,18 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
                return -EPERM;
        }
 
+       if (le32_to_cpu(es->s_blocks_count) + input->blocks_count <
+           le32_to_cpu(es->s_blocks_count)) {
+               ext3_warning(sb, __FUNCTION__, "blocks_count overflow\n");
+               return -EINVAL;
+       }
+
+       if (le32_to_cpu(es->s_inodes_count) + EXT3_INODES_PER_GROUP(sb) <
+           le32_to_cpu(es->s_inodes_count)) {
+               ext3_warning(sb, __FUNCTION__, "inodes_count overflow\n");
+               return -EINVAL;
+       }
+
        if (reserved_gdb || gdb_off == 0) {
                if (!EXT3_HAS_COMPAT_FEATURE(sb,
                                             EXT3_FEATURE_COMPAT_RESIZE_INODE)){
@@ -958,6 +971,11 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es,
 
        add = EXT3_BLOCKS_PER_GROUP(sb) - last;
 
+       if (o_blocks_count + add < o_blocks_count) {
+               ext3_warning(sb, __FUNCTION__, "blocks_count overflow");
+               return -EINVAL;
+       }
+
        if (o_blocks_count + add > n_blocks_count)
                add = n_blocks_count - o_blocks_count;
 
index 3559086eee5fb45ce45a79ed4f076b62759e2ce5..8bfd56ef18ca56d9c584b250b77ab3aa1220a337 100644 (file)
@@ -45,7 +45,7 @@
 static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
                             unsigned long journal_devnum);
 static int ext3_create_journal(struct super_block *, struct ext3_super_block *,
-                              int);
+                              unsigned int);
 static void ext3_commit_super (struct super_block * sb,
                               struct ext3_super_block * es,
                               int sync);
@@ -62,13 +62,13 @@ static void ext3_unlockfs(struct super_block *sb);
 static void ext3_write_super (struct super_block * sb);
 static void ext3_write_super_lockfs(struct super_block *sb);
 
-/* 
+/*
  * Wrappers for journal_start/end.
  *
  * The only special thing we need to do here is to make sure that all
  * journal_end calls result in the superblock being marked dirty, so
  * that sync() will call the filesystem's write_super callback if
- * appropriate. 
+ * appropriate.
  */
 handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks)
 {
@@ -90,11 +90,11 @@ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks)
        return journal_start(journal, nblocks);
 }
 
-/* 
+/*
  * The only special thing we need to do here is to make sure that all
  * journal_stop calls result in the superblock being marked dirty, so
  * that sync() will call the filesystem's write_super callback if
- * appropriate. 
+ * appropriate.
  */
 int __ext3_journal_stop(const char *where, handle_t *handle)
 {
@@ -159,20 +159,21 @@ static void ext3_handle_error(struct super_block *sb)
        if (sb->s_flags & MS_RDONLY)
                return;
 
-       if (test_opt (sb, ERRORS_RO)) {
-               printk (KERN_CRIT "Remounting filesystem read-only\n");
-               sb->s_flags |= MS_RDONLY;
-       } else {
+       if (!test_opt (sb, ERRORS_CONT)) {
                journal_t *journal = EXT3_SB(sb)->s_journal;
 
                EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT;
                if (journal)
                        journal_abort(journal, -EIO);
        }
+       if (test_opt (sb, ERRORS_RO)) {
+               printk (KERN_CRIT "Remounting filesystem read-only\n");
+               sb->s_flags |= MS_RDONLY;
+       }
+       ext3_commit_super(sb, es, 1);
        if (test_opt(sb, ERRORS_PANIC))
                panic("EXT3-fs (device %s): panic forced after error\n",
                        sb->s_id);
-       ext3_commit_super(sb, es, 1);
 }
 
 void ext3_error (struct super_block * sb, const char * function,
@@ -369,16 +370,16 @@ static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi)
 {
        struct list_head *l;
 
-       printk(KERN_ERR "sb orphan head is %d\n", 
+       printk(KERN_ERR "sb orphan head is %d\n",
               le32_to_cpu(sbi->s_es->s_last_orphan));
 
        printk(KERN_ERR "sb_info orphan list:\n");
        list_for_each(l, &sbi->s_orphan) {
                struct inode *inode = orphan_list_entry(l);
                printk(KERN_ERR "  "
-                      "inode %s:%ld at %p: mode %o, nlink %d, next %d\n",
+                      "inode %s:%lu at %p: mode %o, nlink %d, next %d\n",
                       inode->i_sb->s_id, inode->i_ino, inode,
-                      inode->i_mode, inode->i_nlink, 
+                      inode->i_mode, inode->i_nlink,
                       NEXT_ORPHAN(inode));
        }
 }
@@ -475,7 +476,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
                inode_init_once(&ei->vfs_inode);
        }
 }
+
 static int init_inodecache(void)
 {
        ext3_inode_cachep = kmem_cache_create("ext3_inode_cache",
@@ -490,8 +491,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(ext3_inode_cachep))
-               printk(KERN_INFO "ext3_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(ext3_inode_cachep);
 }
 
 static void ext3_clear_inode(struct inode *inode)
@@ -733,8 +733,8 @@ static match_table_t tokens = {
 
 static ext3_fsblk_t get_sb_block(void **data)
 {
-       ext3_fsblk_t    sb_block;
-       char            *options = (char *) *data;
+       ext3_fsblk_t    sb_block;
+       char            *options = (char *) *data;
 
        if (!options || strncmp(options, "sb=", 3) != 0)
                return 1;       /* Default location */
@@ -753,7 +753,7 @@ static ext3_fsblk_t get_sb_block(void **data)
 }
 
 static int parse_options (char *options, struct super_block *sb,
-                         unsigned long *inum, unsigned long *journal_devnum,
+                         unsigned int *inum, unsigned long *journal_devnum,
                          ext3_fsblk_t *n_blocks_count, int is_remount)
 {
        struct ext3_sb_info *sbi = EXT3_SB(sb);
@@ -1174,7 +1174,8 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es,
 static int ext3_check_descriptors (struct super_block * sb)
 {
        struct ext3_sb_info *sbi = EXT3_SB(sb);
-       ext3_fsblk_t block = le32_to_cpu(sbi->s_es->s_first_data_block);
+       ext3_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block);
+       ext3_fsblk_t last_block;
        struct ext3_group_desc * gdp = NULL;
        int desc_block = 0;
        int i;
@@ -1183,12 +1184,17 @@ static int ext3_check_descriptors (struct super_block * sb)
 
        for (i = 0; i < sbi->s_groups_count; i++)
        {
+               if (i == sbi->s_groups_count - 1)
+                       last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
+               else
+                       last_block = first_block +
+                               (EXT3_BLOCKS_PER_GROUP(sb) - 1);
+
                if ((i % EXT3_DESC_PER_BLOCK(sb)) == 0)
                        gdp = (struct ext3_group_desc *)
                                        sbi->s_group_desc[desc_block++]->b_data;
-               if (le32_to_cpu(gdp->bg_block_bitmap) < block ||
-                   le32_to_cpu(gdp->bg_block_bitmap) >=
-                               block + EXT3_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
+                   le32_to_cpu(gdp->bg_block_bitmap) > last_block)
                {
                        ext3_error (sb, "ext3_check_descriptors",
                                    "Block bitmap for group %d"
@@ -1197,9 +1203,8 @@ static int ext3_check_descriptors (struct super_block * sb)
                                        le32_to_cpu(gdp->bg_block_bitmap));
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||
-                   le32_to_cpu(gdp->bg_inode_bitmap) >=
-                               block + EXT3_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||
+                   le32_to_cpu(gdp->bg_inode_bitmap) > last_block)
                {
                        ext3_error (sb, "ext3_check_descriptors",
                                    "Inode bitmap for group %d"
@@ -1208,9 +1213,9 @@ static int ext3_check_descriptors (struct super_block * sb)
                                        le32_to_cpu(gdp->bg_inode_bitmap));
                        return 0;
                }
-               if (le32_to_cpu(gdp->bg_inode_table) < block ||
-                   le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >=
-                   block + EXT3_BLOCKS_PER_GROUP(sb))
+               if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
+                   le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >
+                   last_block)
                {
                        ext3_error (sb, "ext3_check_descriptors",
                                    "Inode table for group %d"
@@ -1219,7 +1224,7 @@ static int ext3_check_descriptors (struct super_block * sb)
                                        le32_to_cpu(gdp->bg_inode_table));
                        return 0;
                }
-               block += EXT3_BLOCKS_PER_GROUP(sb);
+               first_block += EXT3_BLOCKS_PER_GROUP(sb);
                gdp++;
        }
 
@@ -1301,17 +1306,17 @@ static void ext3_orphan_cleanup (struct super_block * sb,
                DQUOT_INIT(inode);
                if (inode->i_nlink) {
                        printk(KERN_DEBUG
-                               "%s: truncating inode %ld to %Ld bytes\n",
+                               "%s: truncating inode %lu to %Ld bytes\n",
                                __FUNCTION__, inode->i_ino, inode->i_size);
-                       jbd_debug(2, "truncating inode %ld to %Ld bytes\n",
+                       jbd_debug(2, "truncating inode %lu to %Ld bytes\n",
                                  inode->i_ino, inode->i_size);
                        ext3_truncate(inode);
                        nr_truncates++;
                } else {
                        printk(KERN_DEBUG
-                               "%s: deleting unreferenced inode %ld\n",
+                               "%s: deleting unreferenced inode %lu\n",
                                __FUNCTION__, inode->i_ino);
-                       jbd_debug(2, "deleting unreferenced inode %ld\n",
+                       jbd_debug(2, "deleting unreferenced inode %lu\n",
                                  inode->i_ino);
                        nr_orphans++;
                }
@@ -1390,7 +1395,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        ext3_fsblk_t sb_block = get_sb_block(&data);
        ext3_fsblk_t logic_sb_block;
        unsigned long offset = 0;
-       unsigned long journal_inum = 0;
+       unsigned int journal_inum = 0;
        unsigned long journal_devnum = 0;
        unsigned long def_mount_opts;
        struct inode *root;
@@ -1401,11 +1406,10 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
        int needs_recovery;
        __le32 features;
 
-       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(*sbi));
        sbi->s_mount_opt = 0;
        sbi->s_resuid = EXT3_DEF_RESUID;
        sbi->s_resgid = EXT3_DEF_RESGID;
@@ -1483,7 +1487,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
            (EXT3_HAS_COMPAT_FEATURE(sb, ~0U) ||
             EXT3_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
             EXT3_HAS_INCOMPAT_FEATURE(sb, ~0U)))
-               printk(KERN_WARNING 
+               printk(KERN_WARNING
                       "EXT3-fs warning: feature flags set on rev 0 fs, "
                       "running e2fsck is recommended\n");
        /*
@@ -1509,7 +1513,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 
        if (blocksize < EXT3_MIN_BLOCK_SIZE ||
            blocksize > EXT3_MAX_BLOCK_SIZE) {
-               printk(KERN_ERR 
+               printk(KERN_ERR
                       "EXT3-fs: Unsupported filesystem blocksize %d on %s.\n",
                       blocksize, sb->s_id);
                goto failed_mount;
@@ -1533,14 +1537,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
                offset = (sb_block * EXT3_MIN_BLOCK_SIZE) % blocksize;
                bh = sb_bread(sb, logic_sb_block);
                if (!bh) {
-                       printk(KERN_ERR 
+                       printk(KERN_ERR
                               "EXT3-fs: Can't read superblock on 2nd try.\n");
                        goto failed_mount;
                }
                es = (struct ext3_super_block *)(((char *)bh->b_data) + offset);
                sbi->s_es = es;
                if (es->s_magic != cpu_to_le16(EXT3_SUPER_MAGIC)) {
-                       printk (KERN_ERR 
+                       printk (KERN_ERR
                                "EXT3-fs: Magic mismatch, very weird !\n");
                        goto failed_mount;
                }
@@ -1622,10 +1626,9 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent)
 
        if (EXT3_BLOCKS_PER_GROUP(sb) == 0)
                goto cantfind_ext3;
-       sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
-                              le32_to_cpu(es->s_first_data_block) +
-                              EXT3_BLOCKS_PER_GROUP(sb) - 1) /
-                             EXT3_BLOCKS_PER_GROUP(sb);
+       sbi->s_groups_count = ((le32_to_cpu(es->s_blocks_count) -
+                              le32_to_cpu(es->s_first_data_block) - 1)
+                                      / EXT3_BLOCKS_PER_GROUP(sb)) + 1;
        db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) /
                   EXT3_DESC_PER_BLOCK(sb);
        sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
@@ -1820,7 +1823,7 @@ out_fail:
 /*
  * Setup any per-fs journal parameters now.  We'll do this both on
  * initial mount, once the journal has been initialised but before we've
- * done any recovery; and again on any subsequent remount. 
+ * done any recovery; and again on any subsequent remount.
  */
 static void ext3_init_journal_params(struct super_block *sb, journal_t *journal)
 {
@@ -1840,7 +1843,8 @@ static void ext3_init_journal_params(struct super_block *sb, journal_t *journal)
        spin_unlock(&journal->j_state_lock);
 }
 
-static journal_t *ext3_get_journal(struct super_block *sb, int journal_inum)
+static journal_t *ext3_get_journal(struct super_block *sb,
+                                  unsigned int journal_inum)
 {
        struct inode *journal_inode;
        journal_t *journal;
@@ -1975,7 +1979,7 @@ static int ext3_load_journal(struct super_block *sb,
                             unsigned long journal_devnum)
 {
        journal_t *journal;
-       int journal_inum = le32_to_cpu(es->s_journal_inum);
+       unsigned int journal_inum = le32_to_cpu(es->s_journal_inum);
        dev_t journal_dev;
        int err = 0;
        int really_read_only;
@@ -2061,7 +2065,7 @@ static int ext3_load_journal(struct super_block *sb,
 
 static int ext3_create_journal(struct super_block * sb,
                               struct ext3_super_block * es,
-                              int journal_inum)
+                              unsigned int journal_inum)
 {
        journal_t *journal;
 
@@ -2074,7 +2078,7 @@ static int ext3_create_journal(struct super_block * sb,
        if (!(journal = ext3_get_journal(sb, journal_inum)))
                return -EINVAL;
 
-       printk(KERN_INFO "EXT3-fs: creating new journal on inode %d\n",
+       printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n",
               journal_inum);
 
        if (journal_create(journal)) {
@@ -2342,10 +2346,8 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
                         */
                        ext3_clear_journal_err(sb, es);
                        sbi->s_mount_state = le16_to_cpu(es->s_state);
-                       if ((ret = ext3_group_extend(sb, es, n_blocks_count))) {
-                               err = ret;
+                       if ((err = ext3_group_extend(sb, es, n_blocks_count)))
                                goto restore_opts;
-                       }
                        if (!ext3_setup_super (sb, es, 0))
                                sb->s_flags &= ~MS_RDONLY;
                }
@@ -2734,7 +2736,7 @@ static int __init init_ext3_fs(void)
 out:
        destroy_inodecache();
 out1:
-       exit_ext3_xattr();
+       exit_ext3_xattr();
        return err;
 }
 
index a44a0562203a3794ac5e82389eb91708e01d036d..f86f2482f01df3a87b8a25ef9941fcc5a3a68b93 100644 (file)
@@ -75,7 +75,7 @@
 
 #ifdef EXT3_XATTR_DEBUG
 # define ea_idebug(inode, f...) do { \
-               printk(KERN_DEBUG "inode %s:%ld: ", \
+               printk(KERN_DEBUG "inode %s:%lu: ", \
                        inode->i_sb->s_id, inode->i_ino); \
                printk(f); \
                printk("\n"); \
@@ -233,7 +233,7 @@ ext3_xattr_block_get(struct inode *inode, int name_index, const char *name,
                atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
        if (ext3_xattr_check_block(bh)) {
 bad_block:     ext3_error(inode->i_sb, __FUNCTION__,
-                          "inode %ld: bad block "E3FSBLK, inode->i_ino,
+                          "inode %lu: bad block "E3FSBLK, inode->i_ino,
                           EXT3_I(inode)->i_file_acl);
                error = -EIO;
                goto cleanup;
@@ -375,7 +375,7 @@ ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size)
                atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount));
        if (ext3_xattr_check_block(bh)) {
                ext3_error(inode->i_sb, __FUNCTION__,
-                          "inode %ld: bad block "E3FSBLK, inode->i_ino,
+                          "inode %lu: bad block "E3FSBLK, inode->i_ino,
                           EXT3_I(inode)->i_file_acl);
                error = -EIO;
                goto cleanup;
@@ -647,7 +647,7 @@ ext3_xattr_block_find(struct inode *inode, struct ext3_xattr_info *i,
                        le32_to_cpu(BHDR(bs->bh)->h_refcount));
                if (ext3_xattr_check_block(bs->bh)) {
                        ext3_error(sb, __FUNCTION__,
-                               "inode %ld: bad block "E3FSBLK, inode->i_ino,
+                               "inode %lu: bad block "E3FSBLK, inode->i_ino,
                                EXT3_I(inode)->i_file_acl);
                        error = -EIO;
                        goto cleanup;
@@ -848,7 +848,7 @@ cleanup_dquot:
 
 bad_block:
        ext3_error(inode->i_sb, __FUNCTION__,
-                  "inode %ld: bad block "E3FSBLK, inode->i_ino,
+                  "inode %lu: bad block "E3FSBLK, inode->i_ino,
                   EXT3_I(inode)->i_file_acl);
        goto cleanup;
 
@@ -1077,14 +1077,14 @@ ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
        bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
        if (!bh) {
                ext3_error(inode->i_sb, __FUNCTION__,
-                       "inode %ld: block "E3FSBLK" read error", inode->i_ino,
+                       "inode %lu: block "E3FSBLK" read error", inode->i_ino,
                        EXT3_I(inode)->i_file_acl);
                goto cleanup;
        }
        if (BHDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
            BHDR(bh)->h_blocks != cpu_to_le32(1)) {
                ext3_error(inode->i_sb, __FUNCTION__,
-                       "inode %ld: bad block "E3FSBLK, inode->i_ino,
+                       "inode %lu: bad block "E3FSBLK, inode->i_ino,
                        EXT3_I(inode)->i_file_acl);
                goto cleanup;
        }
@@ -1211,7 +1211,7 @@ again:
                bh = sb_bread(inode->i_sb, ce->e_block);
                if (!bh) {
                        ext3_error(inode->i_sb, __FUNCTION__,
-                               "inode %ld: block %lu read error",
+                               "inode %lu: block %lu read error",
                                inode->i_ino, (unsigned long) ce->e_block);
                } else if (le32_to_cpu(BHDR(bh)->h_refcount) >=
                                EXT3_XATTR_REFCOUNT_MAX) {
index 97b967b84fc6070b7efc47887345a8e574f5d147..82cc4f59e3bae3302abd291b392eccb90f4e1be4 100644 (file)
@@ -58,8 +58,7 @@ int __init fat_cache_init(void)
 
 void fat_cache_destroy(void)
 {
-       if (kmem_cache_destroy(fat_cache_cachep))
-               printk(KERN_INFO "fat_cache: not all structures were freed\n");
+       kmem_cache_destroy(fat_cache_cachep);
 }
 
 static inline struct fat_cache *fat_cache_alloc(struct inode *inode)
index 31b7174176ba76798284286e8f6767419cef7e12..ab96ae82375305ae295447bbef39a1728894eae0 100644 (file)
@@ -50,14 +50,14 @@ static int fat_add_cluster(struct inode *inode)
        return err;
 }
 
-static int __fat_get_blocks(struct inode *inode, sector_t iblock,
-                           unsigned long *max_blocks,
-                           struct buffer_head *bh_result, int create)
+static inline int __fat_get_block(struct inode *inode, sector_t iblock,
+                                 unsigned long *max_blocks,
+                                 struct buffer_head *bh_result, int create)
 {
        struct super_block *sb = inode->i_sb;
        struct msdos_sb_info *sbi = MSDOS_SB(sb);
-       sector_t phys;
        unsigned long mapped_blocks;
+       sector_t phys;
        int err, offset;
 
        err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
@@ -73,7 +73,7 @@ static int __fat_get_blocks(struct inode *inode, sector_t iblock,
 
        if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) {
                fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)",
-                            MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
+                       MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
                return -EIO;
        }
 
@@ -93,34 +93,29 @@ static int __fat_get_blocks(struct inode *inode, sector_t iblock,
        err = fat_bmap(inode, iblock, &phys, &mapped_blocks);
        if (err)
                return err;
+
        BUG_ON(!phys);
        BUG_ON(*max_blocks != mapped_blocks);
        set_buffer_new(bh_result);
        map_bh(bh_result, sb, phys);
+
        return 0;
 }
 
-static int fat_get_blocks(struct inode *inode, sector_t iblock,
-                         struct buffer_head *bh_result, int create)
+static int fat_get_block(struct inode *inode, sector_t iblock,
+                        struct buffer_head *bh_result, int create)
 {
        struct super_block *sb = inode->i_sb;
-       int err;
        unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits;
+       int err;
 
-       err = __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create);
+       err = __fat_get_block(inode, iblock, &max_blocks, bh_result, create);
        if (err)
                return err;
        bh_result->b_size = max_blocks << sb->s_blocksize_bits;
        return 0;
 }
 
-static int fat_get_block(struct inode *inode, sector_t iblock,
-                        struct buffer_head *bh_result, int create)
-{
-       unsigned long max_blocks = 1;
-       return __fat_get_blocks(inode, iblock, &max_blocks, bh_result, create);
-}
-
 static int fat_writepage(struct page *page, struct writeback_control *wbc)
 {
        return block_write_full_page(page, fat_get_block, wbc);
@@ -188,7 +183,7 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb,
         * condition of fat_get_block() and ->truncate().
         */
        return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov,
-                                 offset, nr_segs, fat_get_blocks, NULL);
+                                 offset, nr_segs, fat_get_block, NULL);
 }
 
 static sector_t _fat_bmap(struct address_space *mapping, sector_t block)
@@ -375,8 +370,6 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
                        inode->i_flags |= S_IMMUTABLE;
        }
        MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
-       /* this is as close to the truth as we can get ... */
-       inode->i_blksize = sbi->cluster_size;
        inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
                           & ~((loff_t)sbi->cluster_size - 1)) >> 9;
        inode->i_mtime.tv_sec =
@@ -528,8 +521,7 @@ static int __init fat_init_inodecache(void)
 
 static void __exit fat_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(fat_inode_cachep))
-               printk(KERN_INFO "fat_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(fat_inode_cachep);
 }
 
 static int fat_remount(struct super_block *sb, int *flags, char *data)
@@ -1137,7 +1129,6 @@ static int fat_read_root(struct inode *inode)
                MSDOS_I(inode)->i_start = 0;
                inode->i_size = sbi->dir_entries * sizeof(struct msdos_dir_entry);
        }
-       inode->i_blksize = sbi->cluster_size;
        inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
                           & ~((loff_t)sbi->cluster_size - 1)) >> 9;
        MSDOS_I(inode)->i_logstart = 0;
@@ -1168,11 +1159,10 @@ int fat_fill_super(struct super_block *sb, void *data, int silent,
        long error;
        char buf[50];
 
-       sbi = kmalloc(sizeof(struct msdos_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct msdos_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct msdos_sb_info));
 
        sb->s_flags |= MS_NODIRATIME;
        sb->s_magic = MSDOS_SUPER_MAGIC;
index b3c6b82e6a9d8629446e77268a83a2c5c4eb1b62..8d3bfca7714bf35e9e982caa761bb5c549909bc6 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -281,10 +281,8 @@ static struct fdtable *alloc_fdtable(int nr)
 out2:
        nfds = fdt->max_fdset;
 out:
-       if (new_openset)
-               free_fdset(new_openset, nfds);
-       if (new_execset)
-               free_fdset(new_execset, nfds);
+       free_fdset(new_openset, nfds);
+       free_fdset(new_execset, nfds);
        kfree(fdt);
        return NULL;
 }
index 0131ba06e1ee48bc9714805efa8b15a11a21edcc..bc35a40417d7ada53223f5c93ed26875af97a646 100644 (file)
@@ -169,7 +169,7 @@ void fastcall __fput(struct file *file)
        if (file->f_op && file->f_op->release)
                file->f_op->release(inode, file);
        security_file_free(file);
-       if (unlikely(inode->i_cdev != NULL))
+       if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))
                cdev_put(inode->i_cdev);
        fops_put(file->f_op);
        if (file->f_mode & FMODE_WRITE)
index d35979a58743599adbd82e61dc83f41bc5658efd..c8a92652612aad1352ba491b50a165624ceaba7a 100644 (file)
@@ -252,7 +252,7 @@ enum {
  * Get filesystem private data from VFS inode.
  */
 #define VXFS_INO(ip) \
-       ((struct vxfs_inode_info *)(ip)->u.generic_ip)
+       ((struct vxfs_inode_info *)(ip)->i_private)
 
 /*
  * Get filesystem private data from VFS superblock.
index ca6a39714771e317a89ad31c48e08c541438206a..4786d51ad3bd59faa1a7a93c7e944f2b6463fa71 100644 (file)
@@ -239,11 +239,10 @@ vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip)
        ip->i_ctime.tv_nsec = 0;
        ip->i_mtime.tv_nsec = 0;
 
-       ip->i_blksize = PAGE_SIZE;
        ip->i_blocks = vip->vii_blocks;
        ip->i_generation = vip->vii_gen;
 
-       ip->u.generic_ip = (void *)vip;
+       ip->i_private = vip;
        
 }
 
@@ -338,5 +337,5 @@ vxfs_read_inode(struct inode *ip)
 void
 vxfs_clear_inode(struct inode *ip)
 {
-       kmem_cache_free(vxfs_inode_cachep, ip->u.generic_ip);
+       kmem_cache_free(vxfs_inode_cachep, ip->i_private);
 }
index 46fe60b2da23b2eafad38d99b62c8edacba4dd1b..79ec1f23d4d2d65718d465f375c3926d9bd8613a 100644 (file)
@@ -23,7 +23,7 @@ static struct fuse_conn *fuse_ctl_file_conn_get(struct file *file)
 {
        struct fuse_conn *fc;
        mutex_lock(&fuse_mutex);
-       fc = file->f_dentry->d_inode->u.generic_ip;
+       fc = file->f_dentry->d_inode->i_private;
        if (fc)
                fc = fuse_conn_get(fc);
        mutex_unlock(&fuse_mutex);
@@ -98,7 +98,7 @@ static struct dentry *fuse_ctl_add_dentry(struct dentry *parent,
                inode->i_op = iop;
        inode->i_fop = fop;
        inode->i_nlink = nlink;
-       inode->u.generic_ip = fc;
+       inode->i_private = fc;
        d_add(dentry, inode);
        return dentry;
 }
@@ -150,7 +150,7 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc)
 
        for (i = fc->ctl_ndents - 1; i >= 0; i--) {
                struct dentry *dentry = fc->ctl_dentry[i];
-               dentry->d_inode->u.generic_ip = NULL;
+               dentry->d_inode->i_private = NULL;
                d_drop(dentry);
                dput(dentry);
        }
index 7d25092262ae71d3eb0af390b60b8e8a0c587a9e..cb7cadb0b7901906e2dfd47bd5f3aac3b3578fb7 100644 (file)
@@ -118,7 +118,6 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr)
        inode->i_uid     = attr->uid;
        inode->i_gid     = attr->gid;
        i_size_write(inode, attr->size);
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks  = attr->blocks;
        inode->i_atime.tv_sec   = attr->atime;
        inode->i_atime.tv_nsec  = attr->atimensec;
index 13231dd5ce660c7ac5e16e476306289b12151c41..0d200068d0afaff014db5279d46c74dab06332bb 100644 (file)
@@ -249,10 +249,9 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
        sb = tree->inode->i_sb;
        size = sizeof(struct hfs_bnode) + tree->pages_per_bnode *
                sizeof(struct page *);
-       node = kmalloc(size, GFP_KERNEL);
+       node = kzalloc(size, GFP_KERNEL);
        if (!node)
                return NULL;
-       memset(node, 0, size);
        node->tree = tree;
        node->this = cnid;
        set_bit(HFS_BNODE_NEW, &node->flags);
index 40035799431992573e1e97f87e25e666f1061ddf..5fd0ed71f92331c3553ef9d563c0543e9fc9e9f6 100644 (file)
@@ -21,10 +21,9 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke
        struct page *page;
        unsigned int size;
 
-       tree = kmalloc(sizeof(*tree), GFP_KERNEL);
+       tree = kzalloc(sizeof(*tree), GFP_KERNEL);
        if (!tree)
                return NULL;
-       memset(tree, 0, sizeof(*tree));
 
        init_MUTEX(&tree->tree_lock);
        spin_lock_init(&tree->hash_lock);
index 315cf44a90b23e60a55910c484a71d661e64fbd2..d05641c35fc902e1f385a076977bc704f1cc05bf 100644 (file)
@@ -154,7 +154,6 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, int mode)
        inode->i_gid = current->fsgid;
        inode->i_nlink = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       inode->i_blksize = HFS_SB(sb)->alloc_blksz;
        HFS_I(inode)->flags = 0;
        HFS_I(inode)->rsrc_inode = NULL;
        HFS_I(inode)->fs_blocks = 0;
@@ -284,7 +283,6 @@ static int hfs_read_inode(struct inode *inode, void *data)
        inode->i_uid = hsb->s_uid;
        inode->i_gid = hsb->s_gid;
        inode->i_nlink = 1;
-       inode->i_blksize = HFS_SB(inode->i_sb)->alloc_blksz;
 
        if (idata->key)
                HFS_I(inode)->cat_key = *idata->key;
index 34937ee83ab1052d2510d1ead5d3ca9fdf78af63..d43b4fcc8ad3967d08d353547af2d1f138e3e282 100644 (file)
@@ -356,11 +356,10 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
        struct inode *root_inode;
        int res;
 
-       sbi = kmalloc(sizeof(struct hfs_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct hfs_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct hfs_sb_info));
        INIT_HLIST_HEAD(&sbi->rsrc_inodes);
 
        res = -EINVAL;
@@ -455,8 +454,7 @@ static int __init init_hfs_fs(void)
 static void __exit exit_hfs_fs(void)
 {
        unregister_filesystem(&hfs_fs_type);
-       if (kmem_cache_destroy(hfs_inode_cachep))
-               printk(KERN_ERR "hfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(hfs_inode_cachep);
 }
 
 module_init(init_hfs_fs)
index 77bf434da6796d89a9181ae50f9af0dd60a6bcf5..29da6574ba77941b22c15b4e959cd4c84b8bbee1 100644 (file)
@@ -409,10 +409,9 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
        sb = tree->inode->i_sb;
        size = sizeof(struct hfs_bnode) + tree->pages_per_bnode *
                sizeof(struct page *);
-       node = kmalloc(size, GFP_KERNEL);
+       node = kzalloc(size, GFP_KERNEL);
        if (!node)
                return NULL;
-       memset(node, 0, size);
        node->tree = tree;
        node->this = cnid;
        set_bit(HFS_BNODE_NEW, &node->flags);
index cfc852fdd1b574b0455db793706018ecdb80aef0..a9b9e872e29a6296ecd4d327bd8f2653beeb7a3e 100644 (file)
@@ -24,10 +24,9 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id)
        struct page *page;
        unsigned int size;
 
-       tree = kmalloc(sizeof(*tree), GFP_KERNEL);
+       tree = kzalloc(sizeof(*tree), GFP_KERNEL);
        if (!tree)
                return NULL;
-       memset(tree, 0, sizeof(*tree));
 
        init_MUTEX(&tree->tree_lock);
        spin_lock_init(&tree->hash_lock);
index 924ecdef8091fa0323ae03e62417263cbc055330..0eb1a60926682bec544dcbd697c293cec407973d 100644 (file)
@@ -304,7 +304,6 @@ struct inode *hfsplus_new_inode(struct super_block *sb, int mode)
        inode->i_gid = current->fsgid;
        inode->i_nlink = 1;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       inode->i_blksize = HFSPLUS_SB(sb).alloc_blksz;
        INIT_LIST_HEAD(&HFSPLUS_I(inode).open_dir_list);
        init_MUTEX(&HFSPLUS_I(inode).extents_lock);
        atomic_set(&HFSPLUS_I(inode).opencnt, 0);
@@ -407,7 +406,6 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
        type = hfs_bnode_read_u16(fd->bnode, fd->entryoffset);
 
        HFSPLUS_I(inode).dev = 0;
-       inode->i_blksize = HFSPLUS_SB(inode->i_sb).alloc_blksz;
        if (type == HFSPLUS_FOLDER) {
                struct hfsplus_cat_folder *folder = &entry.folder;
 
index d279d5924f2857338815f9637567bad248f5a45e..194eede52fa46005949042c37d8e57e3ef8fe7db 100644 (file)
@@ -493,8 +493,7 @@ static int __init init_hfsplus_fs(void)
 static void __exit exit_hfsplus_fs(void)
 {
        unregister_filesystem(&hfsplus_fs_type);
-       if (kmem_cache_destroy(hfsplus_inode_cachep))
-               printk(KERN_ERR "hfsplus_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(hfsplus_inode_cachep);
 }
 
 module_init(init_hfsplus_fs)
index b82e3d9c879021ae9882158aa8df2080c73f144e..322e876c35edd8105d3a49150ced12b0c9efd618 100644 (file)
@@ -156,7 +156,6 @@ static int read_name(struct inode *ino, char *name)
        ino->i_mode = i_mode;
        ino->i_nlink = i_nlink;
        ino->i_size = i_size;
-       ino->i_blksize = i_blksize;
        ino->i_blocks = i_blocks;
        return(0);
 }
index 2807aa833e62011a42ddeea45e8bc46867907229..b52b7381d10f45710f980b885731654fa5e0442d 100644 (file)
@@ -76,7 +76,7 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
                return NULL;
        }
 
-       qbh->data = data = (char *)kmalloc(2048, GFP_NOFS);
+       qbh->data = data = kmalloc(2048, GFP_NOFS);
        if (!data) {
                printk("HPFS: hpfs_map_4sectors: out of memory\n");
                goto bail;
index 56f2c338c4d9a1b9a9639447ae7b23666079b461..bcf6ee36e0656b258d050418de151e910c54ff2e 100644 (file)
@@ -17,7 +17,6 @@ void hpfs_init_inode(struct inode *i)
        i->i_gid = hpfs_sb(sb)->sb_gid;
        i->i_mode = hpfs_sb(sb)->sb_mode;
        hpfs_inode->i_conv = hpfs_sb(sb)->sb_conv;
-       i->i_blksize = 512;
        i->i_size = -1;
        i->i_blocks = -1;
        
index 8fe51c343786e99d22c2abb1b2e5b16b8a997364..450b5e0b4785c59431b002e5aa1db2b33aed70b8 100644 (file)
@@ -203,8 +203,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(hpfs_inode_cachep))
-               printk(KERN_INFO "hpfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(hpfs_inode_cachep);
 }
 
 /*
@@ -462,11 +461,10 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
 
        int o;
 
-       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        s->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(*sbi));
 
        sbi->sb_bmp_dir = NULL;
        sbi->sb_cp_table = NULL;
index 3a9bdf58166f39f1ee946d7e15d8f3b4dc3b40ac..dcb6d2e988b81a3bf86ecabc2a233979c2eff5bc 100644 (file)
@@ -152,7 +152,6 @@ static void hppfs_read_inode(struct inode *ino)
        ino->i_mode = proc_ino->i_mode;
        ino->i_nlink = proc_ino->i_nlink;
        ino->i_size = proc_ino->i_size;
-       ino->i_blksize = proc_ino->i_blksize;
        ino->i_blocks = proc_ino->i_blocks;
 }
 
index c3920c96dadf2f854ab77dcb9741580859f06c95..e025a31b4c64a9f2584e7e2f5e095aae3d8a353c 100644 (file)
@@ -357,7 +357,6 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid,
                inode->i_mode = mode;
                inode->i_uid = uid;
                inode->i_gid = gid;
-               inode->i_blksize = HPAGE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->a_ops = &hugetlbfs_aops;
                inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info;
index 0bf9f0444a964bb5398e50a533a5a942eb701eae..f5c04dd9ae8ae54ba32ebfd4c8cba3bb4001f219 100644 (file)
@@ -163,7 +163,7 @@ static struct inode *alloc_inode(struct super_block *sb)
                                bdi = sb->s_bdev->bd_inode->i_mapping->backing_dev_info;
                        mapping->backing_dev_info = bdi;
                }
-               memset(&inode->u, 0, sizeof(inode->u));
+               inode->i_private = 0;
                inode->i_mapping = mapping;
        }
        return inode;
@@ -254,9 +254,9 @@ void clear_inode(struct inode *inode)
        DQUOT_DROP(inode);
        if (inode->i_sb && inode->i_sb->s_op->clear_inode)
                inode->i_sb->s_op->clear_inode(inode);
-       if (inode->i_bdev)
+       if (S_ISBLK(inode->i_mode) && inode->i_bdev)
                bd_forget(inode);
-       if (inode->i_cdev)
+       if (S_ISCHR(inode->i_mode) && inode->i_cdev)
                cd_forget(inode);
        inode->i_state = I_CLEAR;
 }
index 14391361c8863b63e21fb87f5c2351d752ebcc10..4527692f432b1b262f74bc42027326628e06b5ee 100644 (file)
@@ -96,9 +96,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(isofs_inode_cachep))
-               printk(KERN_INFO "iso_inode_cache: not all structures were "
-                                       "freed\n");
+       kmem_cache_destroy(isofs_inode_cachep);
 }
 
 static int isofs_remount(struct super_block *sb, int *flags, char *data)
@@ -557,11 +555,10 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
        struct iso9660_options          opt;
        struct isofs_sb_info          * sbi;
 
-       sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
+       sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        s->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(*sbi));
 
        if (!parse_options((char *)data, &opt))
                goto out_freesbi;
@@ -1238,7 +1235,7 @@ static void isofs_read_inode(struct inode *inode)
        }
        inode->i_uid = sbi->s_uid;
        inode->i_gid = sbi->s_gid;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
 
        ei->i_format_parm[0] = 0;
        ei->i_format_parm[1] = 0;
@@ -1294,7 +1291,6 @@ static void isofs_read_inode(struct inode *inode)
                              isonum_711 (de->ext_attr_length));
 
        /* Set the number of blocks for stat() - should be done before RR */
-       inode->i_blksize = PAGE_CACHE_SIZE; /* For stat() only */
        inode->i_blocks  = (inode->i_size + 511) >> 9;
 
        /*
index 47678a26c13b271d81cb50c56fa94a3fad5ff0cd..0208cc7ac5d0f0835ed0bceb206cce2baef5fae5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * linux/fs/checkpoint.c
- * 
+ *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  *
  * Copyright 1999 Red Hat Software --- All Rights Reserved
@@ -9,8 +9,8 @@
  * the terms of the GNU General Public License, version 2, or at your
  * option, any later version, incorporated herein by reference.
  *
- * Checkpoint routines for the generic filesystem journaling code.  
- * Part of the ext2fs journaling system.  
+ * Checkpoint routines for the generic filesystem journaling code.
+ * Part of the ext2fs journaling system.
  *
  * Checkpointing is the process of ensuring that a section of the log is
  * committed fully to disk, so that that portion of the log can be
@@ -145,6 +145,7 @@ void __log_wait_for_space(journal_t *journal)
  * jbd_unlock_bh_state().
  */
 static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh)
+       __releases(journal->j_list_lock)
 {
        get_bh(bh);
        spin_unlock(&journal->j_list_lock);
@@ -225,7 +226,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count)
  * Try to flush one buffer from the checkpoint list to disk.
  *
  * Return 1 if something happened which requires us to abort the current
- * scan of the checkpoint list.  
+ * scan of the checkpoint list.
  *
  * Called with j_list_lock held and drops it if 1 is returned
  * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it
@@ -269,7 +270,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
                 * possibly block, while still holding the journal lock.
                 * We cannot afford to let the transaction logic start
                 * messing around with this buffer before we write it to
-                * disk, as that would break recoverability.  
+                * disk, as that would break recoverability.
                 */
                BUFFER_TRACE(bh, "queue");
                get_bh(bh);
@@ -292,7 +293,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
  * Perform an actual checkpoint. We take the first transaction on the
  * list of transactions to be checkpointed and send all its buffers
  * to disk. We submit larger chunks of data at once.
- * 
+ *
  * The journal should be locked before calling this function.
  */
 int log_do_checkpoint(journal_t *journal)
@@ -303,10 +304,10 @@ int log_do_checkpoint(journal_t *journal)
 
        jbd_debug(1, "Start checkpoint\n");
 
-       /* 
+       /*
         * First thing: if there are any transactions in the log which
         * don't need checkpointing, just eliminate them from the
-        * journal straight away.  
+        * journal straight away.
         */
        result = cleanup_journal_tail(journal);
        jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
@@ -384,9 +385,9 @@ out:
  * we have already got rid of any since the last update of the log tail
  * in the journal superblock.  If so, we can instantly roll the
  * superblock forward to remove those transactions from the log.
- * 
+ *
  * Return <0 on error, 0 on success, 1 if there was nothing to clean up.
- * 
+ *
  * Called with the journal lock held.
  *
  * This is the only part of the journaling code which really needs to be
@@ -403,8 +404,8 @@ int cleanup_journal_tail(journal_t *journal)
        unsigned long   blocknr, freed;
 
        /* OK, work out the oldest transaction remaining in the log, and
-        * the log block it starts at. 
-        * 
+        * the log block it starts at.
+        *
         * If the log is now empty, we need to work out which is the
         * next transaction ID we will write, and where it will
         * start. */
@@ -479,7 +480,7 @@ static int journal_clean_one_cp_list(struct journal_head *jh, int *released)
        if (!jh)
                return 0;
 
-       last_jh = jh->b_cpprev;
+       last_jh = jh->b_cpprev;
        do {
                jh = next_jh;
                next_jh = jh->b_cpnext;
@@ -557,7 +558,7 @@ out:
        return ret;
 }
 
-/* 
+/*
  * journal_remove_checkpoint: called after a buffer has been committed
  * to disk (either by being write-back flushed to disk, or being
  * committed to the log).
@@ -635,7 +636,7 @@ out:
  * Called with the journal locked.
  * Called with j_list_lock held.
  */
-void __journal_insert_checkpoint(struct journal_head *jh, 
+void __journal_insert_checkpoint(struct journal_head *jh,
                               transaction_t *transaction)
 {
        JBUFFER_TRACE(jh, "entry");
@@ -657,7 +658,7 @@ void __journal_insert_checkpoint(struct journal_head *jh,
 
 /*
  * We've finished with this transaction structure: adios...
- * 
+ *
  * The transaction must have no links except for the checkpoint by this
  * point.
  *
index f66724ce443a6ab7be44db95aa68f9359c451427..2fc66c3e66818830904603d2023b4bd4422963ed 100644 (file)
@@ -181,7 +181,7 @@ loop:
                                                transaction->t_expires))
                        should_sleep = 0;
                if (journal->j_flags & JFS_UNMOUNT)
-                       should_sleep = 0;
+                       should_sleep = 0;
                if (should_sleep) {
                        spin_unlock(&journal->j_state_lock);
                        schedule();
@@ -271,7 +271,7 @@ static void journal_kill_thread(journal_t *journal)
 int journal_write_metadata_buffer(transaction_t *transaction,
                                  struct journal_head  *jh_in,
                                  struct journal_head **jh_out,
-                                 int blocknr)
+                                 unsigned long blocknr)
 {
        int need_copy_out = 0;
        int done_copy_out = 0;
@@ -578,7 +578,7 @@ int journal_next_log_block(journal_t *journal, unsigned long *retp)
  * this is a no-op.  If needed, we can use j_blk_offset - everything is
  * ready.
  */
-int journal_bmap(journal_t *journal, unsigned long blocknr, 
+int journal_bmap(journal_t *journal, unsigned long blocknr,
                 unsigned long *retp)
 {
        int err = 0;
@@ -696,13 +696,13 @@ fail:
  *  @bdev: Block device on which to create the journal
  *  @fs_dev: Device which hold journalled filesystem for this journal.
  *  @start: Block nr Start of journal.
- *  @len:  Lenght of the journal in blocks.
+ *  @len:  Length of the journal in blocks.
  *  @blocksize: blocksize of journalling device
  *  @returns: a newly created journal_t *
- *  
+ *
  *  journal_init_dev creates a journal which maps a fixed contiguous
  *  range of blocks on an arbitrary block device.
- * 
+ *
  */
 journal_t * journal_init_dev(struct block_device *bdev,
                        struct block_device *fs_dev,
@@ -739,11 +739,11 @@ journal_t * journal_init_dev(struct block_device *bdev,
 
        return journal;
 }
-/** 
+
+/**
  *  journal_t * journal_init_inode () - creates a journal which maps to a inode.
  *  @inode: An inode to create the journal in
- *  
+ *
  * journal_init_inode creates a journal which maps an on-disk inode as
  * the journal.  The inode must exist already, must support bmap() and
  * must have all data blocks preallocated.
@@ -763,7 +763,7 @@ journal_t * journal_init_inode (struct inode *inode)
        journal->j_inode = inode;
        jbd_debug(1,
                  "journal %p: inode %s/%ld, size %Ld, bits %d, blksize %ld\n",
-                 journal, inode->i_sb->s_id, inode->i_ino, 
+                 journal, inode->i_sb->s_id, inode->i_ino,
                  (long long) inode->i_size,
                  inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);
 
@@ -798,10 +798,10 @@ journal_t * journal_init_inode (struct inode *inode)
        return journal;
 }
 
-/* 
+/*
  * If the journal init or create aborts, we need to mark the journal
  * superblock as being NULL to prevent the journal destroy from writing
- * back a bogus superblock. 
+ * back a bogus superblock.
  */
 static void journal_fail_superblock (journal_t *journal)
 {
@@ -820,7 +820,7 @@ static void journal_fail_superblock (journal_t *journal)
 static int journal_reset(journal_t *journal)
 {
        journal_superblock_t *sb = journal->j_superblock;
-       unsigned int first, last;
+       unsigned long first, last;
 
        first = be32_to_cpu(sb->s_first);
        last = be32_to_cpu(sb->s_maxlen);
@@ -844,13 +844,13 @@ static int journal_reset(journal_t *journal)
        return 0;
 }
 
-/** 
+/**
  * int journal_create() - Initialise the new journal file
  * @journal: Journal to create. This structure must have been initialised
- * 
+ *
  * Given a journal_t structure which tells us which disk blocks we can
  * use, create a new journal superblock and initialise all of the
- * journal fields from scratch.  
+ * journal fields from scratch.
  **/
 int journal_create(journal_t *journal)
 {
@@ -915,7 +915,7 @@ int journal_create(journal_t *journal)
        return journal_reset(journal);
 }
 
-/** 
+/**
  * void journal_update_superblock() - Update journal sb on disk.
  * @journal: The journal to update.
  * @wait: Set to '0' if you don't want to wait for IO completion.
@@ -939,7 +939,7 @@ void journal_update_superblock(journal_t *journal, int wait)
                                journal->j_transaction_sequence) {
                jbd_debug(1,"JBD: Skipping superblock update on recovered sb "
                        "(start %ld, seq %d, errno %d)\n",
-                       journal->j_tail, journal->j_tail_sequence, 
+                       journal->j_tail, journal->j_tail_sequence,
                        journal->j_errno);
                goto out;
        }
@@ -1062,7 +1062,7 @@ static int load_superblock(journal_t *journal)
 /**
  * int journal_load() - Read journal from disk.
  * @journal: Journal to act on.
- * 
+ *
  * Given a journal_t structure which tells us which disk blocks contain
  * a journal, read the journal from disk to initialise the in-memory
  * structures.
@@ -1094,7 +1094,7 @@ int journal_load(journal_t *journal)
        /*
         * Create a slab for this blocksize
         */
-       err = journal_create_jbd_slab(cpu_to_be32(sb->s_blocksize));
+       err = journal_create_jbd_slab(be32_to_cpu(sb->s_blocksize));
        if (err)
                return err;
 
@@ -1172,9 +1172,9 @@ void journal_destroy(journal_t *journal)
  * @compat: bitmask of compatible features
  * @ro: bitmask of features that force read-only mount
  * @incompat: bitmask of incompatible features
- * 
+ *
  * Check whether the journal uses all of a given set of
- * features.  Return true (non-zero) if it does. 
+ * features.  Return true (non-zero) if it does.
  **/
 
 int journal_check_used_features (journal_t *journal, unsigned long compat,
@@ -1203,7 +1203,7 @@ int journal_check_used_features (journal_t *journal, unsigned long compat,
  * @compat: bitmask of compatible features
  * @ro: bitmask of features that force read-only mount
  * @incompat: bitmask of incompatible features
- * 
+ *
  * Check whether the journaling code supports the use of
  * all of a given set of features on this journal.  Return true
  * (non-zero) if it can. */
@@ -1241,7 +1241,7 @@ int journal_check_available_features (journal_t *journal, unsigned long compat,
  * @incompat: bitmask of incompatible features
  *
  * Mark a given journal feature as present on the
- * superblock.  Returns true if the requested features could be set. 
+ * superblock.  Returns true if the requested features could be set.
  *
  */
 
@@ -1327,7 +1327,7 @@ static int journal_convert_superblock_v1(journal_t *journal,
 /**
  * int journal_flush () - Flush journal
  * @journal: Journal to act on.
- * 
+ *
  * Flush all data for a given journal to disk and empty the journal.
  * Filesystems can use this when remounting readonly to ensure that
  * recovery does not need to happen on remount.
@@ -1394,7 +1394,7 @@ int journal_flush(journal_t *journal)
  * int journal_wipe() - Wipe journal contents
  * @journal: Journal to act on.
  * @write: flag (see below)
- * 
+ *
  * Wipe out all of the contents of a journal, safely.  This will produce
  * a warning if the journal contains any valid recovery information.
  * Must be called between journal_init_*() and journal_load().
@@ -1449,7 +1449,7 @@ static const char *journal_dev_name(journal_t *journal, char *buffer)
 
 /*
  * Journal abort has very specific semantics, which we describe
- * for journal abort. 
+ * for journal abort.
  *
  * Two internal function, which provide abort to te jbd layer
  * itself are here.
@@ -1504,7 +1504,7 @@ static void __journal_abort_soft (journal_t *journal, int errno)
  * Perform a complete, immediate shutdown of the ENTIRE
  * journal (not of a single transaction).  This operation cannot be
  * undone without closing and reopening the journal.
- *           
+ *
  * The journal_abort function is intended to support higher level error
  * recovery mechanisms such as the ext2/ext3 remount-readonly error
  * mode.
@@ -1538,7 +1538,7 @@ static void __journal_abort_soft (journal_t *journal, int errno)
  * supply an errno; a null errno implies that absolutely no further
  * writes are done to the journal (unless there are any already in
  * progress).
- * 
+ *
  */
 
 void journal_abort(journal_t *journal, int errno)
@@ -1546,7 +1546,7 @@ void journal_abort(journal_t *journal, int errno)
        __journal_abort_soft(journal, errno);
 }
 
-/** 
+/**
  * int journal_errno () - returns the journal's error state.
  * @journal: journal to examine.
  *
@@ -1570,7 +1570,7 @@ int journal_errno(journal_t *journal)
        return err;
 }
 
-/** 
+/**
  * int journal_clear_err () - clears the journal's error state
  * @journal: journal to act on.
  *
@@ -1590,7 +1590,7 @@ int journal_clear_err(journal_t *journal)
        return err;
 }
 
-/** 
+/**
  * void journal_ack_err() - Ack journal err.
  * @journal: journal to act on.
  *
@@ -1612,7 +1612,7 @@ int journal_blocks_per_page(struct inode *inode)
 
 /*
  * Simple support for retrying memory allocations.  Introduced to help to
- * debug different VM deadlock avoidance strategies. 
+ * debug different VM deadlock avoidance strategies.
  */
 void * __jbd_kmalloc (const char *where, size_t size, gfp_t flags, int retry)
 {
@@ -2047,13 +2047,7 @@ static int __init journal_init(void)
 {
        int ret;
 
-/* Static check for data structure consistency.  There's no code
- * invoked --- we'll just get a linker failure if things aren't right.
- */
-       extern void journal_bad_superblock_size(void);
-       if (sizeof(struct journal_superblock_s) != 1024)
-               journal_bad_superblock_size();
-
+       BUILD_BUG_ON(sizeof(struct journal_superblock_s) != 1024);
 
        ret = journal_init_caches();
        if (ret != 0)
index de5bafb4e8534db59d76f86bf6352821a6458012..445eed6ce5dc6d0c9196aab99b68d0e53cad1a67 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * linux/fs/recovery.c
- * 
+ *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  *
  * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
@@ -10,7 +10,7 @@
  * option, any later version, incorporated herein by reference.
  *
  * Journal recovery routines for the generic filesystem journaling code;
- * part of the ext2fs journaling system.  
+ * part of the ext2fs journaling system.
  */
 
 #ifndef __KERNEL__
@@ -25,9 +25,9 @@
 
 /*
  * Maintain information about the progress of the recovery job, so that
- * the different passes can carry information between them. 
+ * the different passes can carry information between them.
  */
-struct recovery_info 
+struct recovery_info
 {
        tid_t           start_transaction;
        tid_t           end_transaction;
@@ -116,7 +116,7 @@ static int do_readahead(journal_t *journal, unsigned int start)
        err = 0;
 
 failed:
-       if (nbufs) 
+       if (nbufs)
                journal_brelse_array(bufs, nbufs);
        return err;
 }
@@ -128,7 +128,7 @@ failed:
  * Read a block from the journal
  */
 
-static int jread(struct buffer_head **bhp, journal_t *journal, 
+static int jread(struct buffer_head **bhp, journal_t *journal,
                 unsigned int offset)
 {
        int err;
@@ -212,14 +212,14 @@ do {                                                                      \
 /**
  * journal_recover - recovers a on-disk journal
  * @journal: the journal to recover
- * 
+ *
  * The primary function for recovering the log contents when mounting a
- * journaled device.  
+ * journaled device.
  *
  * Recovery is done in three passes.  In the first pass, we look for the
  * end of the log.  In the second, we assemble the list of revoke
  * blocks.  In the third and final pass, we replay any un-revoked blocks
- * in the log.  
+ * in the log.
  */
 int journal_recover(journal_t *journal)
 {
@@ -231,10 +231,10 @@ int journal_recover(journal_t *journal)
        memset(&info, 0, sizeof(info));
        sb = journal->j_superblock;
 
-       /* 
+       /*
         * The journal superblock's s_start field (the current log head)
         * is always zero if, and only if, the journal was cleanly
-        * unmounted.  
+        * unmounted.
         */
 
        if (!sb->s_start) {
@@ -253,7 +253,7 @@ int journal_recover(journal_t *journal)
        jbd_debug(0, "JBD: recovery, exit status %d, "
                  "recovered transactions %u to %u\n",
                  err, info.start_transaction, info.end_transaction);
-       jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n", 
+       jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
                  info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
 
        /* Restart the log at the next transaction ID, thus invalidating
@@ -268,15 +268,15 @@ int journal_recover(journal_t *journal)
 /**
  * journal_skip_recovery - Start journal and wipe exiting records
  * @journal: journal to startup
- * 
+ *
  * Locate any valid recovery information from the journal and set up the
  * journal structures in memory to ignore it (presumably because the
- * caller has evidence that it is out of date).  
+ * caller has evidence that it is out of date).
  * This function does'nt appear to be exorted..
  *
  * We perform one pass over the journal to allow us to tell the user how
  * much recovery information is being erased, and to let us initialise
- * the journal transaction sequence numbers to the next unused ID. 
+ * the journal transaction sequence numbers to the next unused ID.
  */
 int journal_skip_recovery(journal_t *journal)
 {
@@ -297,7 +297,7 @@ int journal_skip_recovery(journal_t *journal)
 #ifdef CONFIG_JBD_DEBUG
                int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence);
 #endif
-               jbd_debug(0, 
+               jbd_debug(0,
                          "JBD: ignoring %d transaction%s from the journal.\n",
                          dropped, (dropped == 1) ? "" : "s");
                journal->j_transaction_sequence = ++info.end_transaction;
@@ -314,7 +314,7 @@ static int do_one_pass(journal_t *journal,
        unsigned long           next_log_block;
        int                     err, success = 0;
        journal_superblock_t *  sb;
-       journal_header_t *      tmp;
+       journal_header_t *      tmp;
        struct buffer_head *    bh;
        unsigned int            sequence;
        int                     blocktype;
@@ -324,10 +324,10 @@ static int do_one_pass(journal_t *journal,
        MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
                               / sizeof(journal_block_tag_t));
 
-       /* 
+       /*
         * First thing is to establish what we expect to find in the log
         * (in terms of transaction IDs), and where (in terms of log
-        * block offsets): query the superblock.  
+        * block offsets): query the superblock.
         */
 
        sb = journal->j_superblock;
@@ -344,7 +344,7 @@ static int do_one_pass(journal_t *journal,
         * Now we walk through the log, transaction by transaction,
         * making sure that each transaction has a commit block in the
         * expected place.  Each complete transaction gets replayed back
-        * into the main filesystem. 
+        * into the main filesystem.
         */
 
        while (1) {
@@ -379,8 +379,8 @@ static int do_one_pass(journal_t *journal,
                next_log_block++;
                wrap(journal, next_log_block);
 
-               /* What kind of buffer is it? 
-                * 
+               /* What kind of buffer is it?
+                *
                 * If it is a descriptor block, check that it has the
                 * expected sequence number.  Otherwise, we're all done
                 * here. */
@@ -394,7 +394,7 @@ static int do_one_pass(journal_t *journal,
 
                blocktype = be32_to_cpu(tmp->h_blocktype);
                sequence = be32_to_cpu(tmp->h_sequence);
-               jbd_debug(3, "Found magic %d, sequence %d\n", 
+               jbd_debug(3, "Found magic %d, sequence %d\n",
                          blocktype, sequence);
 
                if (sequence != next_commit_ID) {
@@ -438,7 +438,7 @@ static int do_one_pass(journal_t *journal,
                                        /* Recover what we can, but
                                         * report failure at the end. */
                                        success = err;
-                                       printk (KERN_ERR 
+                                       printk (KERN_ERR
                                                "JBD: IO error %d recovering "
                                                "block %ld in log\n",
                                                err, io_block);
@@ -452,7 +452,7 @@ static int do_one_pass(journal_t *journal,
                                         * revoked, then we're all done
                                         * here. */
                                        if (journal_test_revoke
-                                           (journal, blocknr, 
+                                           (journal, blocknr,
                                             next_commit_ID)) {
                                                brelse(obh);
                                                ++info->nr_revoke_hits;
@@ -465,7 +465,7 @@ static int do_one_pass(journal_t *journal,
                                                        blocknr,
                                                        journal->j_blocksize);
                                        if (nbh == NULL) {
-                                               printk(KERN_ERR 
+                                               printk(KERN_ERR
                                                       "JBD: Out of memory "
                                                       "during recovery.\n");
                                                err = -ENOMEM;
@@ -537,7 +537,7 @@ static int do_one_pass(journal_t *journal,
        }
 
  done:
-       /* 
+       /*
         * We broke out of the log scan loop: either we came to the
         * known end of the log or we found an unexpected block in the
         * log.  If the latter happened, then we know that the "current"
@@ -567,7 +567,7 @@ static int do_one_pass(journal_t *journal,
 
 /* Scan a revoke record, marking all blocks mentioned as revoked. */
 
-static int scan_revoke_records(journal_t *journal, struct buffer_head *bh, 
+static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
                               tid_t sequence, struct recovery_info *info)
 {
        journal_revoke_header_t *header;
index a56144183462e20d06ad756a5b6d062c44333838..c532429d8d9b365e9b540255e4f684071a9e0894 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * linux/fs/revoke.c
- * 
+ *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 2000
  *
  * Copyright 2000 Red Hat corp --- All Rights Reserved
  * Revoke is the mechanism used to prevent old log records for deleted
  * metadata from being replayed on top of newer data using the same
  * blocks.  The revoke mechanism is used in two separate places:
- * 
+ *
  * + Commit: during commit we write the entire list of the current
  *   transaction's revoked blocks to the journal
- * 
+ *
  * + Recovery: during recovery we record the transaction ID of all
  *   revoked blocks.  If there are multiple revoke records in the log
  *   for a single block, only the last one counts, and if there is a log
@@ -29,7 +29,7 @@
  * single transaction:
  *
  * Block is revoked and then journaled:
- *   The desired end result is the journaling of the new block, so we 
+ *   The desired end result is the journaling of the new block, so we
  *   cancel the revoke before the transaction commits.
  *
  * Block is journaled and then revoked:
@@ -41,7 +41,7 @@
  *   transaction must have happened after the block was journaled and so
  *   the revoke must take precedence.
  *
- * Block is revoked and then written as data: 
+ * Block is revoked and then written as data:
  *   The data write is allowed to succeed, but the revoke is _not_
  *   cancelled.  We still need to prevent old log records from
  *   overwriting the new data.  We don't even need to clear the revoke
@@ -54,7 +54,7 @@
  *                     buffer has not been revoked, and cancel_revoke
  *                     need do nothing.
  * RevokeValid set, Revoked set:
- *                     buffer has been revoked.  
+ *                     buffer has been revoked.
  */
 
 #ifndef __KERNEL__
@@ -77,7 +77,7 @@ static kmem_cache_t *revoke_table_cache;
    journal replay, this involves recording the transaction ID of the
    last transaction to revoke this block. */
 
-struct jbd_revoke_record_s 
+struct jbd_revoke_record_s
 {
        struct list_head  hash;
        tid_t             sequence;     /* Used for recovery only */
@@ -90,8 +90,8 @@ struct jbd_revoke_table_s
 {
        /* It is conceivable that we might want a larger hash table
         * for recovery.  Must be a power of two. */
-       int               hash_size; 
-       int               hash_shift; 
+       int               hash_size;
+       int               hash_shift;
        struct list_head *hash_table;
 };
 
@@ -301,22 +301,22 @@ void journal_destroy_revoke(journal_t *journal)
 
 #ifdef __KERNEL__
 
-/* 
+/*
  * journal_revoke: revoke a given buffer_head from the journal.  This
  * prevents the block from being replayed during recovery if we take a
  * crash after this current transaction commits.  Any subsequent
  * metadata writes of the buffer in this transaction cancel the
- * revoke.  
+ * revoke.
  *
  * Note that this call may block --- it is up to the caller to make
  * sure that there are no further calls to journal_write_metadata
  * before the revoke is complete.  In ext3, this implies calling the
  * revoke before clearing the block bitmap when we are deleting
- * metadata. 
+ * metadata.
  *
  * Revoke performs a journal_forget on any buffer_head passed in as a
  * parameter, but does _not_ forget the buffer_head if the bh was only
- * found implicitly. 
+ * found implicitly.
  *
  * bh_in may not be a journalled buffer - it may have come off
  * the hash tables without an attached journal_head.
@@ -325,7 +325,7 @@ void journal_destroy_revoke(journal_t *journal)
  * by one.
  */
 
-int journal_revoke(handle_t *handle, unsigned long blocknr, 
+int journal_revoke(handle_t *handle, unsigned long blocknr,
                   struct buffer_head *bh_in)
 {
        struct buffer_head *bh = NULL;
@@ -487,7 +487,7 @@ void journal_switch_revoke_table(journal_t *journal)
        else
                journal->j_revoke = journal->j_revoke_table[0];
 
-       for (i = 0; i < journal->j_revoke->hash_size; i++) 
+       for (i = 0; i < journal->j_revoke->hash_size; i++)
                INIT_LIST_HEAD(&journal->j_revoke->hash_table[i]);
 }
 
@@ -498,7 +498,7 @@ void journal_switch_revoke_table(journal_t *journal)
  * Called with the journal lock held.
  */
 
-void journal_write_revoke_records(journal_t *journal, 
+void journal_write_revoke_records(journal_t *journal,
                                  transaction_t *transaction)
 {
        struct journal_head *descriptor;
@@ -507,7 +507,7 @@ void journal_write_revoke_records(journal_t *journal,
        struct list_head *hash_list;
        int i, offset, count;
 
-       descriptor = NULL; 
+       descriptor = NULL;
        offset = 0;
        count = 0;
 
@@ -519,10 +519,10 @@ void journal_write_revoke_records(journal_t *journal,
                hash_list = &revoke->hash_table[i];
 
                while (!list_empty(hash_list)) {
-                       record = (struct jbd_revoke_record_s *) 
+                       record = (struct jbd_revoke_record_s *)
                                hash_list->next;
                        write_one_revoke_record(journal, transaction,
-                                               &descriptor, &offset, 
+                                               &descriptor, &offset,
                                                record);
                        count++;
                        list_del(&record->hash);
@@ -534,14 +534,14 @@ void journal_write_revoke_records(journal_t *journal,
        jbd_debug(1, "Wrote %d revoke records\n", count);
 }
 
-/* 
+/*
  * Write out one revoke record.  We need to create a new descriptor
- * block if the old one is full or if we have not already created one.  
+ * block if the old one is full or if we have not already created one.
  */
 
-static void write_one_revoke_record(journal_t *journal, 
+static void write_one_revoke_record(journal_t *journal,
                                    transaction_t *transaction,
-                                   struct journal_head **descriptorp, 
+                                   struct journal_head **descriptorp,
                                    int *offsetp,
                                    struct jbd_revoke_record_s *record)
 {
@@ -584,21 +584,21 @@ static void write_one_revoke_record(journal_t *journal,
                *descriptorp = descriptor;
        }
 
-       * ((__be32 *)(&jh2bh(descriptor)->b_data[offset])) = 
+       * ((__be32 *)(&jh2bh(descriptor)->b_data[offset])) =
                cpu_to_be32(record->blocknr);
        offset += 4;
        *offsetp = offset;
 }
 
-/* 
+/*
  * Flush a revoke descriptor out to the journal.  If we are aborting,
  * this is a noop; otherwise we are generating a buffer which needs to
  * be waited for during commit, so it has to go onto the appropriate
  * journal buffer list.
  */
 
-static void flush_descriptor(journal_t *journal, 
-                            struct journal_head *descriptor, 
+static void flush_descriptor(journal_t *journal,
+                            struct journal_head *descriptor,
                             int offset)
 {
        journal_revoke_header_t *header;
@@ -618,7 +618,7 @@ static void flush_descriptor(journal_t *journal,
 }
 #endif
 
-/* 
+/*
  * Revoke support for recovery.
  *
  * Recovery needs to be able to:
@@ -629,7 +629,7 @@ static void flush_descriptor(journal_t *journal,
  *  check whether a given block in a given transaction should be replayed
  *  (ie. has not been revoked by a revoke record in that or a subsequent
  *  transaction)
- * 
+ *
  *  empty the revoke table after recovery.
  */
 
@@ -637,11 +637,11 @@ static void flush_descriptor(journal_t *journal,
  * First, setting revoke records.  We create a new revoke record for
  * every block ever revoked in the log as we scan it for recovery, and
  * we update the existing records if we find multiple revokes for a
- * single block. 
+ * single block.
  */
 
-int journal_set_revoke(journal_t *journal, 
-                      unsigned long blocknr, 
+int journal_set_revoke(journal_t *journal,
+                      unsigned long blocknr,
                       tid_t sequence)
 {
        struct jbd_revoke_record_s *record;
@@ -653,18 +653,18 @@ int journal_set_revoke(journal_t *journal,
                if (tid_gt(sequence, record->sequence))
                        record->sequence = sequence;
                return 0;
-       } 
+       }
        return insert_revoke_hash(journal, blocknr, sequence);
 }
 
-/* 
+/*
  * Test revoke records.  For a given block referenced in the log, has
  * that block been revoked?  A revoke record with a given transaction
  * sequence number revokes all blocks in that transaction and earlier
  * ones, but later transactions still need replayed.
  */
 
-int journal_test_revoke(journal_t *journal, 
+int journal_test_revoke(journal_t *journal,
                        unsigned long blocknr,
                        tid_t sequence)
 {
index f5169a96260edc9a95cd3fb61b8f188aa71c43df..e1b3c8af4d1767cd8b530e90cb482655f891fa6f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * linux/fs/transaction.c
- * 
+ *
  * Written by Stephen C. Tweedie <sct@redhat.com>, 1998
  *
  * Copyright 1998 Red Hat corp --- All Rights Reserved
@@ -10,7 +10,7 @@
  * option, any later version, incorporated herein by reference.
  *
  * Generic filesystem transaction handling code; part of the ext2fs
- * journaling system.  
+ * journaling system.
  *
  * This file manages transactions (compound commits managed by the
  * journaling code) and handles (individual atomic operations by the
@@ -74,7 +74,7 @@ get_transaction(journal_t *journal, transaction_t *transaction)
  * start_this_handle: Given a handle, deal with any locking or stalling
  * needed to make sure that there is enough journal space for the handle
  * to begin.  Attach the handle to a transaction and set up the
- * transaction's buffer credits.  
+ * transaction's buffer credits.
  */
 
 static int start_this_handle(journal_t *journal, handle_t *handle)
@@ -117,7 +117,7 @@ repeat_locked:
        if (is_journal_aborted(journal) ||
            (journal->j_errno != 0 && !(journal->j_flags & JFS_ACK_ERR))) {
                spin_unlock(&journal->j_state_lock);
-               ret = -EROFS; 
+               ret = -EROFS;
                goto out;
        }
 
@@ -182,7 +182,7 @@ repeat_locked:
                goto repeat;
        }
 
-       /* 
+       /*
         * The commit code assumes that it can get enough log space
         * without forcing a checkpoint.  This is *critical* for
         * correctness: a checkpoint of a buffer which is also
@@ -191,7 +191,7 @@ repeat_locked:
         *
         * We must therefore ensure the necessary space in the journal
         * *before* starting to dirty potentially checkpointed buffers
-        * in the new transaction. 
+        * in the new transaction.
         *
         * The worst part is, any transaction currently committing can
         * reduce the free space arbitrarily.  Be careful to account for
@@ -246,13 +246,13 @@ static handle_t *new_handle(int nblocks)
 }
 
 /**
- * handle_t *journal_start() - Obtain a new handle.  
+ * handle_t *journal_start() - Obtain a new handle.
  * @journal: Journal to start transaction on.
  * @nblocks: number of block buffer we might modify
  *
  * We make sure that the transaction can guarantee at least nblocks of
  * modified buffers in the log.  We block until the log can guarantee
- * that much space.  
+ * that much space.
  *
  * This function is visible to journal users (like ext3fs), so is not
  * called with the journal already locked.
@@ -292,11 +292,11 @@ handle_t *journal_start(journal_t *journal, int nblocks)
  * int journal_extend() - extend buffer credits.
  * @handle:  handle to 'extend'
  * @nblocks: nr blocks to try to extend by.
- * 
+ *
  * Some transactions, such as large extends and truncates, can be done
  * atomically all at once or in several stages.  The operation requests
  * a credit for a number of buffer modications in advance, but can
- * extend its credit if it needs more.  
+ * extend its credit if it needs more.
  *
  * journal_extend tries to give the running handle more buffer credits.
  * It does not guarantee that allocation - this is a best-effort only.
@@ -363,7 +363,7 @@ out:
  * int journal_restart() - restart a handle .
  * @handle:  handle to restart
  * @nblocks: nr credits requested
- * 
+ *
  * Restart a handle for a multi-transaction filesystem
  * operation.
  *
@@ -462,7 +462,7 @@ void journal_lock_updates(journal_t *journal)
 /**
  * void journal_unlock_updates (journal_t* journal) - release barrier
  * @journal:  Journal to release the barrier on.
- * 
+ *
  * Release a transaction barrier obtained with journal_lock_updates().
  *
  * Should be called without the journal lock held.
@@ -547,8 +547,8 @@ repeat:
        jbd_lock_bh_state(bh);
 
        /* We now hold the buffer lock so it is safe to query the buffer
-        * state.  Is the buffer dirty? 
-        * 
+        * state.  Is the buffer dirty?
+        *
         * If so, there are two possibilities.  The buffer may be
         * non-journaled, and undergoing a quite legitimate writeback.
         * Otherwise, it is journaled, and we don't expect dirty buffers
@@ -566,7 +566,7 @@ repeat:
                 */
                if (jh->b_transaction) {
                        J_ASSERT_JH(jh,
-                               jh->b_transaction == transaction || 
+                               jh->b_transaction == transaction ||
                                jh->b_transaction ==
                                        journal->j_committing_transaction);
                        if (jh->b_next_transaction)
@@ -580,7 +580,7 @@ repeat:
                 */
                JBUFFER_TRACE(jh, "Unexpected dirty buffer");
                jbd_unexpected_dirty_buffer(jh);
-       }
+       }
 
        unlock_buffer(bh);
 
@@ -653,7 +653,7 @@ repeat:
                 * buffer had better remain locked during the kmalloc,
                 * but that should be true --- we hold the journal lock
                 * still and the buffer is already on the BUF_JOURNAL
-                * list so won't be flushed. 
+                * list so won't be flushed.
                 *
                 * Subtle point, though: if this is a get_undo_access,
                 * then we will be relying on the frozen_data to contain
@@ -765,8 +765,8 @@ int journal_get_write_access(handle_t *handle, struct buffer_head *bh)
  * manually rather than reading off disk), then we need to keep the
  * buffer_head locked until it has been completely filled with new
  * data.  In this case, we should be able to make the assertion that
- * the bh is not already part of an existing transaction.  
- * 
+ * the bh is not already part of an existing transaction.
+ *
  * The buffer should already be locked by the caller by this point.
  * There is no lock ranking violation: it was a newly created,
  * unlocked buffer beforehand. */
@@ -778,7 +778,7 @@ int journal_get_write_access(handle_t *handle, struct buffer_head *bh)
  *
  * Call this if you create a new bh.
  */
-int journal_get_create_access(handle_t *handle, struct buffer_head *bh) 
+int journal_get_create_access(handle_t *handle, struct buffer_head *bh)
 {
        transaction_t *transaction = handle->h_transaction;
        journal_t *journal = transaction->t_journal;
@@ -847,13 +847,13 @@ out:
  * do not reuse freed space until the deallocation has been committed,
  * since if we overwrote that space we would make the delete
  * un-rewindable in case of a crash.
- * 
+ *
  * To deal with that, journal_get_undo_access requests write access to a
  * buffer for parts of non-rewindable operations such as delete
  * operations on the bitmaps.  The journaling code must keep a copy of
  * the buffer's contents prior to the undo_access call until such time
  * as we know that the buffer has definitely been committed to disk.
- * 
+ *
  * We never need to know which transaction the committed data is part
  * of, buffers touched here are guaranteed to be dirtied later and so
  * will be committed to a new transaction in due course, at which point
@@ -911,13 +911,13 @@ out:
        return err;
 }
 
-/** 
+/**
  * int journal_dirty_data() -  mark a buffer as containing dirty data which
  *                             needs to be flushed before we can commit the
- *                             current transaction.  
+ *                             current transaction.
  * @handle: transaction
  * @bh: bufferhead to mark
- * 
+ *
  * The buffer is placed on the transaction's data list and is marked as
  * belonging to the transaction.
  *
@@ -946,15 +946,15 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh)
 
        /*
         * What if the buffer is already part of a running transaction?
-        * 
+        *
         * There are two cases:
         * 1) It is part of the current running transaction.  Refile it,
         *    just in case we have allocated it as metadata, deallocated
-        *    it, then reallocated it as data. 
+        *    it, then reallocated it as data.
         * 2) It is part of the previous, still-committing transaction.
         *    If all we want to do is to guarantee that the buffer will be
         *    written to disk before this new transaction commits, then
-        *    being sure that the *previous* transaction has this same 
+        *    being sure that the *previous* transaction has this same
         *    property is sufficient for us!  Just leave it on its old
         *    transaction.
         *
@@ -1076,18 +1076,18 @@ no_journal:
        return 0;
 }
 
-/** 
+/**
  * int journal_dirty_metadata() -  mark a buffer as containing dirty metadata
  * @handle: transaction to add buffer to.
- * @bh: buffer to mark 
- * 
+ * @bh: buffer to mark
+ *
  * mark dirty metadata which needs to be journaled as part of the current
  * transaction.
  *
  * The buffer is placed on the transaction's metadata list and is marked
- * as belonging to the transaction.  
+ * as belonging to the transaction.
  *
- * Returns error number or 0 on success.  
+ * Returns error number or 0 on success.
  *
  * Special care needs to be taken if the buffer already belongs to the
  * current committing transaction (in which case we should have frozen
@@ -1135,11 +1135,11 @@ int journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
 
        set_buffer_jbddirty(bh);
 
-       /* 
+       /*
         * Metadata already on the current transaction list doesn't
         * need to be filed.  Metadata on another transaction's list must
         * be committing, and will be refiled once the commit completes:
-        * leave it alone for now. 
+        * leave it alone for now.
         */
        if (jh->b_transaction != transaction) {
                JBUFFER_TRACE(jh, "already on other transaction");
@@ -1165,7 +1165,7 @@ out:
        return 0;
 }
 
-/* 
+/*
  * journal_release_buffer: undo a get_write_access without any buffer
  * updates, if the update decided in the end that it didn't need access.
  *
@@ -1176,20 +1176,20 @@ journal_release_buffer(handle_t *handle, struct buffer_head *bh)
        BUFFER_TRACE(bh, "entry");
 }
 
-/** 
+/**
  * void journal_forget() - bforget() for potentially-journaled buffers.
  * @handle: transaction handle
  * @bh:     bh to 'forget'
  *
  * We can only do the bforget if there are no commits pending against the
  * buffer.  If the buffer is dirty in the current running transaction we
- * can safely unlink it. 
+ * can safely unlink it.
  *
  * bh may not be a journalled buffer at all - it may be a non-JBD
  * buffer which came off the hashtable.  Check for this.
  *
  * Decrements bh->b_count by one.
- * 
+ *
  * Allow this call even if the handle has aborted --- it may be part of
  * the caller's cleanup after an abort.
  */
@@ -1237,7 +1237,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
 
                drop_reserve = 1;
 
-               /* 
+               /*
                 * We are no longer going to journal this buffer.
                 * However, the commit of this transaction is still
                 * important to the buffer: the delete that we are now
@@ -1246,7 +1246,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
                 *
                 * So, if we have a checkpoint on the buffer, we should
                 * now refile the buffer on our BJ_Forget list so that
-                * we know to remove the checkpoint after we commit. 
+                * we know to remove the checkpoint after we commit.
                 */
 
                if (jh->b_cp_transaction) {
@@ -1264,7 +1264,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh)
                        }
                }
        } else if (jh->b_transaction) {
-               J_ASSERT_JH(jh, (jh->b_transaction == 
+               J_ASSERT_JH(jh, (jh->b_transaction ==
                                 journal->j_committing_transaction));
                /* However, if the buffer is still owned by a prior
                 * (committing) transaction, we can't drop it yet... */
@@ -1294,7 +1294,7 @@ drop:
 /**
  * int journal_stop() - complete a transaction
  * @handle: tranaction to complete.
- * 
+ *
  * All done for a particular handle.
  *
  * There is not much action needed here.  We just return any remaining
@@ -1303,7 +1303,7 @@ drop:
  * filesystem is marked for synchronous update.
  *
  * journal_stop itself will not usually return an error, but it may
- * do so in unusual circumstances.  In particular, expect it to 
+ * do so in unusual circumstances.  In particular, expect it to
  * return -EIO if a journal_abort has been executed since the
  * transaction began.
  */
@@ -1373,7 +1373,7 @@ int journal_stop(handle_t *handle)
        if (handle->h_sync ||
                        transaction->t_outstanding_credits >
                                journal->j_max_transaction_buffers ||
-                       time_after_eq(jiffies, transaction->t_expires)) {
+                       time_after_eq(jiffies, transaction->t_expires)) {
                /* Do this even for aborted journals: an abort still
                 * completes the commit thread, it just doesn't write
                 * anything to disk. */
@@ -1388,7 +1388,7 @@ int journal_stop(handle_t *handle)
 
                /*
                 * Special case: JFS_SYNC synchronous updates require us
-                * to wait for the commit to complete.  
+                * to wait for the commit to complete.
                 */
                if (handle->h_sync && !(current->flags & PF_MEMALLOC))
                        err = log_wait_commit(journal, tid);
@@ -1439,7 +1439,7 @@ int journal_force_commit(journal_t *journal)
  * jbd_lock_bh_state(jh2bh(jh)) is held.
  */
 
-static inline void 
+static inline void
 __blist_add_buffer(struct journal_head **list, struct journal_head *jh)
 {
        if (!*list) {
@@ -1454,7 +1454,7 @@ __blist_add_buffer(struct journal_head **list, struct journal_head *jh)
        }
 }
 
-/* 
+/*
  * Remove a buffer from a transaction list, given the transaction's list
  * head pointer.
  *
@@ -1475,7 +1475,7 @@ __blist_del_buffer(struct journal_head **list, struct journal_head *jh)
        jh->b_tnext->b_tprev = jh->b_tprev;
 }
 
-/* 
+/*
  * Remove a buffer from the appropriate transaction list.
  *
  * Note that this function can *change* the value of
@@ -1595,17 +1595,17 @@ out:
 }
 
 
-/** 
+/**
  * int journal_try_to_free_buffers() - try to free page buffers.
  * @journal: journal for operation
  * @page: to try and free
  * @unused_gfp_mask: unused
  *
- * 
+ *
  * For all the buffers on this page,
  * if they are fully written out ordered data, move them onto BUF_CLEAN
  * so try_to_free_buffers() can reap them.
- * 
+ *
  * This function returns non-zero if we wish try_to_free_buffers()
  * to be called. We do this if the page is releasable by try_to_free_buffers().
  * We also do it if the page has locked or dirty buffers and the caller wants
@@ -1629,7 +1629,7 @@ out:
  * cannot happen because we never reallocate freed data as metadata
  * while the data is part of a transaction.  Yes?
  */
-int journal_try_to_free_buffers(journal_t *journal, 
+int journal_try_to_free_buffers(journal_t *journal,
                                struct page *page, gfp_t unused_gfp_mask)
 {
        struct buffer_head *head;
@@ -1697,7 +1697,7 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
 }
 
 /*
- * journal_invalidatepage 
+ * journal_invalidatepage
  *
  * This code is tricky.  It has a number of cases to deal with.
  *
@@ -1705,15 +1705,15 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
  *
  * i_size must be updated on disk before we start calling invalidatepage on the
  * data.
- * 
+ *
  *  This is done in ext3 by defining an ext3_setattr method which
  *  updates i_size before truncate gets going.  By maintaining this
  *  invariant, we can be sure that it is safe to throw away any buffers
  *  attached to the current transaction: once the transaction commits,
  *  we know that the data will not be needed.
- * 
+ *
  *  Note however that we can *not* throw away data belonging to the
- *  previous, committing transaction!  
+ *  previous, committing transaction!
  *
  * Any disk blocks which *are* part of the previous, committing
  * transaction (and which therefore cannot be discarded immediately) are
@@ -1732,7 +1732,7 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
  * don't make guarantees about the order in which data hits disk --- in
  * particular we don't guarantee that new dirty data is flushed before
  * transaction commit --- so it is always safe just to discard data
- * immediately in that mode.  --sct 
+ * immediately in that mode.  --sct
  */
 
 /*
@@ -1876,9 +1876,9 @@ zap_buffer_unlocked:
        return may_free;
 }
 
-/** 
+/**
  * void journal_invalidatepage()
- * @journal: journal to use for flush... 
+ * @journal: journal to use for flush...
  * @page:    page to flush
  * @offset:  length of page to invalidate.
  *
@@ -1886,7 +1886,7 @@ zap_buffer_unlocked:
  *
  */
 void journal_invalidatepage(journal_t *journal,
-                     struct page *page, 
+                     struct page *page,
                      unsigned long offset)
 {
        struct buffer_head *head, *bh, *next;
@@ -1908,7 +1908,7 @@ void journal_invalidatepage(journal_t *journal,
                next = bh->b_this_page;
 
                if (offset <= curr_off) {
-                       /* This block is wholly outside the truncation point */
+                       /* This block is wholly outside the truncation point */
                        lock_buffer(bh);
                        may_free &= journal_unmap_buffer(journal, bh);
                        unlock_buffer(bh);
@@ -1924,8 +1924,8 @@ void journal_invalidatepage(journal_t *journal,
        }
 }
 
-/* 
- * File a buffer on the given transaction list. 
+/*
+ * File a buffer on the given transaction list.
  */
 void __journal_file_buffer(struct journal_head *jh,
                        transaction_t *transaction, int jlist)
@@ -1948,7 +1948,7 @@ void __journal_file_buffer(struct journal_head *jh,
         * with __jbd_unexpected_dirty_buffer()'s handling of dirty
         * state. */
 
-       if (jlist == BJ_Metadata || jlist == BJ_Reserved || 
+       if (jlist == BJ_Metadata || jlist == BJ_Reserved ||
            jlist == BJ_Shadow || jlist == BJ_Forget) {
                if (test_clear_buffer_dirty(bh) ||
                    test_clear_buffer_jbddirty(bh))
@@ -2008,7 +2008,7 @@ void journal_file_buffer(struct journal_head *jh,
        jbd_unlock_bh_state(jh2bh(jh));
 }
 
-/* 
+/*
  * Remove a buffer from its current buffer list in preparation for
  * dropping it from its current transaction entirely.  If the buffer has
  * already started to be used by a subsequent transaction, refile the
@@ -2060,7 +2060,7 @@ void __journal_refile_buffer(struct journal_head *jh)
  * to the caller to remove the journal_head if necessary.  For the
  * unlocked journal_refile_buffer call, the caller isn't going to be
  * doing anything else to the buffer so we need to do the cleanup
- * ourselves to avoid a jh leak. 
+ * ourselves to avoid a jh leak.
  *
  * *** The journal_head may be freed by this call! ***
  */
index 93068697a9bf2cf5b8a438ea96cf72da2d59be1a..f5cf9c93e24380ef1c5347749f4d1f3d5c7d38cb 100644 (file)
@@ -364,12 +364,11 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode,
        inode->i_ctime.tv_nsec = 0;
        inode->i_mtime.tv_nsec = 0;
        inode->i_atime.tv_nsec = 0;
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = (inode->i_size + 511) >> 9;
 
        f = jffs_find_file(c, raw_inode->ino);
 
-       inode->u.generic_ip = (void *)f;
+       inode->i_private = (void *)f;
        insert_inode_hash(inode);
 
        return inode;
@@ -442,7 +441,7 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        });
 
        result = -ENOTDIR;
-       if (!(old_dir_f = (struct jffs_file *)old_dir->u.generic_ip)) {
+       if (!(old_dir_f = old_dir->i_private)) {
                D(printk("jffs_rename(): Old dir invalid.\n"));
                goto jffs_rename_end;
        }
@@ -456,7 +455,7 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        /* Find the new directory.  */
        result = -ENOTDIR;
-       if (!(new_dir_f = (struct jffs_file *)new_dir->u.generic_ip)) {
+       if (!(new_dir_f = new_dir->i_private)) {
                D(printk("jffs_rename(): New dir invalid.\n"));
                goto jffs_rename_end;
        }
@@ -593,7 +592,7 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                }
                else {
                        ddino = ((struct jffs_file *)
-                                inode->u.generic_ip)->pino;
+                                inode->i_private)->pino;
                }
                D3(printk("jffs_readdir(): \"..\" %u\n", ddino));
                if (filldir(dirent, "..", 2, filp->f_pos, ddino, DT_DIR) < 0) {
@@ -604,7 +603,7 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                }
                filp->f_pos++;
        }
-       f = ((struct jffs_file *)inode->u.generic_ip)->children;
+       f = ((struct jffs_file *)inode->i_private)->children;
 
        j = 2;
        while(f && (f->deleted || j++ < filp->f_pos )) {
@@ -652,7 +651,7 @@ jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
        lock_kernel();
 
        D3({
-               char *s = (char *)kmalloc(len + 1, GFP_KERNEL);
+               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);
@@ -668,7 +667,7 @@ jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
        }
 
        r = -EACCES;
-       if (!(d = (struct jffs_file *)dir->u.generic_ip)) {
+       if (!(d = (struct jffs_file *)dir->i_private)) {
                D(printk("jffs_lookup(): No such inode! (%lu)\n",
                         dir->i_ino));
                goto jffs_lookup_end;
@@ -739,7 +738,7 @@ jffs_do_readpage_nolock(struct file *file, struct page *page)
        unsigned long read_len;
        int result;
        struct inode *inode = (struct inode*)page->mapping->host;
-       struct jffs_file *f = (struct jffs_file *)inode->u.generic_ip;
+       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;
@@ -828,7 +827,7 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        });
 
        lock_kernel();
-       dir_f = (struct jffs_file *)dir->u.generic_ip;
+       dir_f = dir->i_private;
 
        ASSERT(if (!dir_f) {
                printk(KERN_ERR "jffs_mkdir(): No reference to a "
@@ -972,7 +971,7 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
                kfree(_name);
        });
 
-       dir_f = (struct jffs_file *) dir->u.generic_ip;
+       dir_f = dir->i_private;
        c = dir_f->c;
 
        result = -ENOENT;
@@ -1082,7 +1081,7 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
        if (!old_valid_dev(rdev))
                return -EINVAL;
        lock_kernel();
-       dir_f = (struct jffs_file *)dir->u.generic_ip;
+       dir_f = dir->i_private;
        c = dir_f->c;
 
        D3(printk (KERN_NOTICE "mknod(): down biglock\n"));
@@ -1173,8 +1172,8 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        lock_kernel();
        D1({
                int len = dentry->d_name.len; 
-               char *_name = (char *)kmalloc(len + 1, GFP_KERNEL);
-               char *_symname = (char *)kmalloc(symname_len + 1, GFP_KERNEL);
+               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);
@@ -1186,7 +1185,7 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
                kfree(_symname);
        });
 
-       dir_f = (struct jffs_file *)dir->u.generic_ip;
+       dir_f = dir->i_private;
        ASSERT(if (!dir_f) {
                printk(KERN_ERR "jffs_symlink(): No reference to a "
                       "jffs_file struct in inode.\n");
@@ -1282,14 +1281,14 @@ jffs_create(struct inode *dir, struct dentry *dentry, int mode,
        lock_kernel();
        D1({
                int len = dentry->d_name.len;
-               char *s = (char *)kmalloc(len + 1, GFP_KERNEL);
+               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 = (struct jffs_file *)dir->u.generic_ip;
+       dir_f = dir->i_private;
        ASSERT(if (!dir_f) {
                printk(KERN_ERR "jffs_create(): No reference to a "
                       "jffs_file struct in inode.\n");
@@ -1403,9 +1402,9 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
                goto out_isem;
        }
 
-       if (!(f = (struct jffs_file *)inode->u.generic_ip)) {
-               D(printk("jffs_file_write(): inode->u.generic_ip = 0x%p\n",
-                               inode->u.generic_ip));
+       if (!(f = inode->i_private)) {
+               D(printk("jffs_file_write(): inode->i_private = 0x%p\n",
+                               inode->i_private));
                goto out_isem;
        }
 
@@ -1693,7 +1692,7 @@ jffs_read_inode(struct inode *inode)
                mutex_unlock(&c->fmc->biglock);
                return;
        }
-       inode->u.generic_ip = (void *)f;
+       inode->i_private = f;
        inode->i_mode = f->mode;
        inode->i_nlink = f->nlink;
        inode->i_uid = f->uid;
@@ -1706,7 +1705,6 @@ jffs_read_inode(struct inode *inode)
        inode->i_mtime.tv_nsec = 
        inode->i_ctime.tv_nsec = 0;
 
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = (inode->i_size + 511) >> 9;
        if (S_ISREG(inode->i_mode)) {
                inode->i_op = &jffs_file_inode_operations;
@@ -1748,7 +1746,7 @@ jffs_delete_inode(struct inode *inode)
        lock_kernel();
        inode->i_size = 0;
        inode->i_blocks = 0;
-       inode->u.generic_ip = NULL;
+       inode->i_private = NULL;
        clear_inode(inode);
        if (inode->i_nlink == 0) {
                c = (struct jffs_control *) inode->i_sb->s_fs_info;
index 9000f1effedf9523991c5692f0c61238e1645809..4a543e1149700b08141d6769814848ea9295e2c9 100644 (file)
@@ -488,13 +488,11 @@ jffs_create_file(struct jffs_control *c,
 {
        struct jffs_file *f;
 
-       if (!(f = (struct jffs_file *)kmalloc(sizeof(struct jffs_file),
-                                             GFP_KERNEL))) {
+       if (!(f = kzalloc(sizeof(*f), GFP_KERNEL))) {
                D(printk("jffs_create_file(): Failed!\n"));
                return NULL;
        }
        no_jffs_file++;
-       memset(f, 0, sizeof(struct jffs_file));
        f->ino = raw_inode->ino;
        f->pino = raw_inode->pino;
        f->nlink = raw_inode->nlink;
@@ -516,7 +514,7 @@ jffs_create_control(struct super_block *sb)
 
        D2(printk("jffs_create_control()\n"));
 
-       if (!(c = (struct jffs_control *)kmalloc(s, GFP_KERNEL))) {
+       if (!(c = kmalloc(s, GFP_KERNEL))) {
                goto fail_control;
        }
        DJM(no_jffs_control++);
@@ -524,7 +522,7 @@ jffs_create_control(struct super_block *sb)
        c->gc_task = NULL;
        c->hash_len = JFFS_HASH_SIZE;
        s = sizeof(struct list_head) * c->hash_len;
-       if (!(c->hash = (struct list_head *)kmalloc(s, GFP_KERNEL))) {
+       if (!(c->hash = kmalloc(s, GFP_KERNEL))) {
                goto fail_hash;
        }
        DJM(no_hash++);
@@ -593,8 +591,7 @@ jffs_add_virtual_root(struct jffs_control *c)
        D2(printk("jffs_add_virtual_root(): "
                  "Creating a virtual root directory.\n"));
 
-       if (!(root = (struct jffs_file *)kmalloc(sizeof(struct jffs_file),
-                                                GFP_KERNEL))) {
+       if (!(root = kmalloc(sizeof(struct jffs_file), GFP_KERNEL))) {
                return -ENOMEM;
        }
        no_jffs_file++;
index 7d8ca1aeace2f85937384dba8b906fe4020d6de4..29b68d939bd9e9f6f9c8bd0572d1b157f2476dcd 100644 (file)
@@ -94,8 +94,7 @@ jffs_build_begin(struct jffs_control *c, int unit)
        struct mtd_info *mtd;
        
        D3(printk("jffs_build_begin()\n"));
-       fmc = (struct jffs_fmcontrol *)kmalloc(sizeof(struct jffs_fmcontrol),
-                                              GFP_KERNEL);
+       fmc = kmalloc(sizeof(*fmc), GFP_KERNEL);
        if (!fmc) {
                D(printk("jffs_build_begin(): Allocation of "
                         "struct jffs_fmcontrol failed!\n"));
@@ -486,8 +485,7 @@ jffs_add_node(struct jffs_node *node)
 
        D3(printk("jffs_add_node(): ino = %u\n", node->ino));
 
-       ref = (struct jffs_node_ref *)kmalloc(sizeof(struct jffs_node_ref),
-                                             GFP_KERNEL);
+       ref = kmalloc(sizeof(*ref), GFP_KERNEL);
        if (!ref)
                return -ENOMEM;
 
index 4780f82825d6fc3bbea2562b0ab245c40088625f..72d9909d95ff360e095b34a3b80320082c4ec1f2 100644 (file)
@@ -263,7 +263,6 @@ void jffs2_read_inode (struct inode *inode)
 
        inode->i_nlink = f->inocache->nlink;
 
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = (inode->i_size + 511) >> 9;
 
        switch (inode->i_mode & S_IFMT) {
@@ -449,7 +448,6 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
        inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
        ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime));
 
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = 0;
        inode->i_size = 0;
 
index 68e3953419b4324504cbe8723a9b62e1cb48b3da..6de374513c010790ab15e40f4103781f669d93c8 100644 (file)
@@ -119,10 +119,9 @@ static int jffs2_get_sb_mtd(struct file_system_type *fs_type,
        struct jffs2_sb_info *c;
        int ret;
 
-       c = kmalloc(sizeof(*c), GFP_KERNEL);
+       c = kzalloc(sizeof(*c), GFP_KERNEL);
        if (!c)
                return -ENOMEM;
-       memset(c, 0, sizeof(*c));
        c->mtd = mtd;
 
        sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c);
index 4d52593a5fc669a018cbd09066e52cb269f18a15..4c74f0944f7ea20ccad8343b02d1edcd85af95dc 100644 (file)
@@ -468,7 +468,7 @@ int extRecord(struct inode *ip, xad_t * xp)
 int extFill(struct inode *ip, xad_t * xp)
 {
        int rc, nbperpage = JFS_SBI(ip->i_sb)->nbperpage;
-       s64 blkno = offsetXAD(xp) >> ip->i_blksize;
+       s64 blkno = offsetXAD(xp) >> ip->i_blkbits;
 
 //      assert(ISSPARSE(ip));
 
index ccbe60aff83de64edddc27381e020c83240adb1b..369d7f39c040a94d0720c884d5dbc6c4ceaa54bc 100644 (file)
@@ -3115,7 +3115,6 @@ static int copy_from_dinode(struct dinode * dip, struct inode *ip)
        ip->i_mtime.tv_nsec = le32_to_cpu(dip->di_mtime.tv_nsec);
        ip->i_ctime.tv_sec = le32_to_cpu(dip->di_ctime.tv_sec);
        ip->i_ctime.tv_nsec = le32_to_cpu(dip->di_ctime.tv_nsec);
-       ip->i_blksize = ip->i_sb->s_blocksize;
        ip->i_blocks = LBLK2PBLK(ip->i_sb, le64_to_cpu(dip->di_nblocks));
        ip->i_generation = le32_to_cpu(dip->di_gen);
 
index 495df402916dbf5d3ff77415aec2085e9f50daf8..bffaca9ae3a20ef31e737485230b0836d666887a 100644 (file)
@@ -115,7 +115,6 @@ struct inode *ialloc(struct inode *parent, umode_t mode)
        }
        jfs_inode->mode2 |= mode;
 
-       inode->i_blksize = sb->s_blocksize;
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        jfs_inode->otime = inode->i_ctime.tv_sec;
index e1e0a6e6ebdfb8d0e1c591a124a249e908fb2174..f5afc129d6b12d2c9483574441f7b7296fb15cac 100644 (file)
@@ -257,7 +257,7 @@ static sector_t metapage_get_blocks(struct inode *inode, sector_t lblock,
        int rc = 0;
        int xflag;
        s64 xaddr;
-       sector_t file_blocks = (inode->i_size + inode->i_blksize - 1) >>
+       sector_t file_blocks = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
                               inode->i_blkbits;
 
        if (lblock >= file_blocks)
index efbb586bed4bcc25db3e8b270bae3720fe7d5ab1..3856efc399c11d7f28a58e24b21f7e9db05a0909 100644 (file)
@@ -282,7 +282,7 @@ int txInit(void)
        TxLockVHWM = (nTxLock * 8) / 10;
 
        size = sizeof(struct tblock) * nTxBlock;
-       TxBlock = (struct tblock *) vmalloc(size);
+       TxBlock = vmalloc(size);
        if (TxBlock == NULL)
                return -ENOMEM;
 
@@ -307,7 +307,7 @@ int txInit(void)
         * tlock id = 0 is reserved.
         */
        size = sizeof(struct tlock) * nTxLock;
-       TxLock = (struct tlock *) vmalloc(size);
+       TxLock = vmalloc(size);
        if (TxLock == NULL) {
                vfree(TxBlock);
                return -ENOMEM;
index ac02ea602c3df2d7194e21c87f133786731bf7ee..8db5afb7b0a7dec0cc8c6bf372c2445050f54b1f 100644 (file)
@@ -383,7 +383,6 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
                return -ENOMEM;
        inode->i_mode = S_IFDIR | 0755;
        inode->i_uid = inode->i_gid = 0;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        inode->i_op = &simple_dir_inode_operations;
@@ -405,7 +404,6 @@ int simple_fill_super(struct super_block *s, int magic, struct tree_descr *files
                        goto out;
                inode->i_mode = S_IFREG | files->mode;
                inode->i_uid = inode->i_gid = 0;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                inode->i_fop = files->ops;
@@ -547,7 +545,7 @@ int simple_attr_open(struct inode *inode, struct file *file,
 
        attr->get = get;
        attr->set = set;
-       attr->data = inode->u.generic_ip;
+       attr->data = inode->i_private;
        attr->fmt = fmt;
        mutex_init(&attr->mutex);
 
index 52774feab93f3c4736febeeca2146a7dad2b9dfc..f95cc3f3c42db4ff709cd2a4f203d78a619323b6 100644 (file)
@@ -160,7 +160,7 @@ static void nlmclnt_prepare_reclaim(struct nlm_host *host)
         */
        list_splice_init(&host->h_granted, &host->h_reclaim);
 
-       dprintk("NLM: reclaiming locks for host %s", host->h_name);
+       dprintk("NLM: reclaiming locks for host %s\n", host->h_name);
 }
 
 static void nlmclnt_finish_reclaim(struct nlm_host *host)
index 50dbb67ae0c4bb271d60784135dfc0bf7cd8e6e2..271e2165fff6ebf8577f4f5ab590a911ec9bedfe 100644 (file)
@@ -100,7 +100,7 @@ static struct nlm_lockowner *nlm_find_lockowner(struct nlm_host *host, fl_owner_
        res = __nlm_find_lockowner(host, owner);
        if (res == NULL) {
                spin_unlock(&host->h_lock);
-               new = (struct nlm_lockowner *)kmalloc(sizeof(*new), GFP_KERNEL);
+               new = kmalloc(sizeof(*new), GFP_KERNEL);
                spin_lock(&host->h_lock);
                res = __nlm_find_lockowner(host, owner);
                if (res == NULL && new != NULL) {
index 703fb038c813c352430295c3537b6a7cc32debf8..a0d0b58ce7a49968aa8ed942d00fbec3e9fc9539 100644 (file)
@@ -99,9 +99,9 @@ nlm_lookup_host(int server, struct sockaddr_in *sin,
        /* Ooops, no host found, create it */
        dprintk("lockd: creating host entry\n");
 
-       if (!(host = (struct nlm_host *) kmalloc(sizeof(*host), GFP_KERNEL)))
+       host = kzalloc(sizeof(*host), GFP_KERNEL);
+       if (!host)
                goto nohost;
-       memset(host, 0, sizeof(*host));
 
        addr = sin->sin_addr.s_addr;
        sprintf(host->h_name, "%u.%u.%u.%u", NIPQUAD(addr));
index 01b4db9e5466d51f98383c221e41a8ede824421c..a92dd98f84013dbece84aa0367f7ed869f487c92 100644 (file)
@@ -100,11 +100,10 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
        nlm_debug_print_fh("creating file for", f);
 
        nfserr = nlm_lck_denied_nolocks;
-       file = (struct nlm_file *) kmalloc(sizeof(*file), GFP_KERNEL);
+       file = kzalloc(sizeof(*file), GFP_KERNEL);
        if (!file)
                goto out_unlock;
 
-       memset(file, 0, sizeof(*file));
        memcpy(&file->f_handle, f, sizeof(struct nfs_fh));
        file->f_hash = hash;
        init_MUTEX(&file->f_sema);
index 4a6abc49418ef9917106d3ed6077be25154e57e4..df6b1075b5494dd380dbe374e0be88239e8b93e8 100644 (file)
@@ -254,7 +254,7 @@ struct inode * minix_new_inode(const struct inode * dir, int * error)
        inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
        inode->i_ino = j;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        memset(&minix_i(inode)->u, 0, sizeof(minix_i(inode)->u));
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
index 330ff9fc7cf065eb0b41871be0ee9a542a6a92e3..c11a4b9fb863c5e10ae342b5637dd1ddd4dc1145 100644 (file)
@@ -90,8 +90,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(minix_inode_cachep))
-               printk(KERN_INFO "minix_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(minix_inode_cachep);
 }
 
 static struct super_operations minix_sops = {
@@ -145,11 +144,10 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
        struct inode *root_inode;
        struct minix_sb_info *sbi;
 
-       sbi = kmalloc(sizeof(struct minix_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct minix_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
        s->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct minix_sb_info));
 
        /* N.B. These should be compile-time tests.
           Unfortunately that is impossible. */
@@ -207,10 +205,9 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
        if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0)
                goto out_illegal_sb;
        i = (sbi->s_imap_blocks + sbi->s_zmap_blocks) * sizeof(bh);
-       map = kmalloc(i, GFP_KERNEL);
+       map = kzalloc(i, GFP_KERNEL);
        if (!map)
                goto out_no_map;
-       memset(map, 0, i);
        sbi->s_imap = &map[0];
        sbi->s_zmap = &map[sbi->s_imap_blocks];
 
@@ -399,7 +396,7 @@ static void V1_minix_read_inode(struct inode * inode)
        inode->i_mtime.tv_nsec = 0;
        inode->i_atime.tv_nsec = 0;
        inode->i_ctime.tv_nsec = 0;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        for (i = 0; i < 9; i++)
                minix_inode->u.i1_data[i] = raw_inode->i_zone[i];
        minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
@@ -432,7 +429,7 @@ static void V2_minix_read_inode(struct inode * inode)
        inode->i_mtime.tv_nsec = 0;
        inode->i_atime.tv_nsec = 0;
        inode->i_ctime.tv_nsec = 0;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        for (i = 0; i < 10; i++)
                minix_inode->u.i2_data[i] = raw_inode->i_zone[i];
        minix_set_inode(inode, old_decode_dev(raw_inode->i_zone[0]));
index 6b591c01b09fcbff6775cbcb8ca7fc8a62c195ca..808e4ea2bb9413a446743fbcdf10caae8d0baf2f 100644 (file)
@@ -372,6 +372,30 @@ void release_open_intent(struct nameidata *nd)
                fput(nd->intent.open.file);
 }
 
+static inline struct dentry *
+do_revalidate(struct dentry *dentry, struct nameidata *nd)
+{
+       int status = dentry->d_op->d_revalidate(dentry, nd);
+       if (unlikely(status <= 0)) {
+               /*
+                * The dentry failed validation.
+                * If d_revalidate returned 0 attempt to invalidate
+                * the dentry otherwise d_revalidate is asking us
+                * to return a fail status.
+                */
+               if (!status) {
+                       if (!d_invalidate(dentry)) {
+                               dput(dentry);
+                               dentry = NULL;
+                       }
+               } else {
+                       dput(dentry);
+                       dentry = ERR_PTR(status);
+               }
+       }
+       return dentry;
+}
+
 /*
  * Internal lookup() using the new generic dcache.
  * SMP-safe
@@ -386,12 +410,9 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
        if (!dentry)
                dentry = d_lookup(parent, name);
 
-       if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
-               if (!dentry->d_op->d_revalidate(dentry, nd) && !d_invalidate(dentry)) {
-                       dput(dentry);
-                       dentry = NULL;
-               }
-       }
+       if (dentry && dentry->d_op && dentry->d_op->d_revalidate)
+               dentry = do_revalidate(dentry, nd);
+
        return dentry;
 }
 
@@ -484,10 +505,9 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
         */
        mutex_unlock(&dir->i_mutex);
        if (result->d_op && result->d_op->d_revalidate) {
-               if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
-                       dput(result);
+               result = do_revalidate(result, nd);
+               if (!result)
                        result = ERR_PTR(-ENOENT);
-               }
        }
        return result;
 }
@@ -767,12 +787,12 @@ need_lookup:
        goto done;
 
 need_revalidate:
-       if (dentry->d_op->d_revalidate(dentry, nd))
-               goto done;
-       if (d_invalidate(dentry))
-               goto done;
-       dput(dentry);
-       goto need_lookup;
+       dentry = do_revalidate(dentry, nd);
+       if (!dentry)
+               goto need_lookup;
+       if (IS_ERR(dentry))
+               goto fail;
+       goto done;
 
 fail:
        return PTR_ERR(dentry);
index fa7ed6a9fc2d2cf79a2633f8f6834311f8051be3..36d180858136fb46e256fcc6550baf7ea6c2dbed 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/acct.h>
 #include <linux/capability.h>
 #include <linux/module.h>
+#include <linux/sysfs.h>
 #include <linux/seq_file.h>
 #include <linux/namespace.h>
 #include <linux/namei.h>
 
 extern int __init init_rootfs(void);
 
-#ifdef CONFIG_SYSFS
-extern int __init sysfs_init(void);
-#else
-static inline int sysfs_init(void)
-{
-       return 0;
-}
-#endif
-
 /* spinlock for vfsmount related operations, inplace of dcache_lock */
 __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
 
index 1ddf77b0b825d08282944604e582b78244852704..42e3bef270c9d0c029475800fec5023229dfe512 100644 (file)
@@ -81,8 +81,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(ncp_inode_cachep))
-               printk(KERN_INFO "ncp_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(ncp_inode_cachep);
 }
 
 static int ncp_remount(struct super_block *sb, int *flags, char* data)
@@ -224,7 +223,6 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
        inode->i_nlink = 1;
        inode->i_uid = server->m.uid;
        inode->i_gid = server->m.gid;
-       inode->i_blksize = NCP_BLOCK_SIZE;
 
        ncp_update_dates(inode, &nwinfo->i);
        ncp_update_inode(inode, nwinfo);
@@ -411,11 +409,10 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
 #endif
        struct ncp_entry_info finfo;
 
-       server = kmalloc(sizeof(struct ncp_server), GFP_KERNEL);
+       server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
        if (!server)
                return -ENOMEM;
        sb->s_fs_info = server;
-       memset(server, 0, sizeof(struct ncp_server));
 
        error = -EFAULT;
        if (raw_data == NULL)
index ca92c240663564c319627de827c58deed0a635ea..e3d26c1bd105a388cf032c3586b192e6b5e56907 100644 (file)
@@ -48,7 +48,7 @@ static int ncp_symlink_readpage(struct file *file, struct page *page)
        char *buf = kmap(page);
 
        error = -ENOMEM;
-       rawlink=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
+       rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
        if (!rawlink)
                goto fail;
 
@@ -126,7 +126,7 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
        /* EPERM is returned by VFS if symlink procedure does not exist */
                return -EPERM;
   
-       rawlink=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
+       rawlink = kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_KERNEL);
        if (!rawlink)
                return -ENOMEM;
 
index 57133678db1660a9599d5b724929a8886bcf97e0..841c99a9b11c84203cb5afbcb9d69f38f3682319 100644 (file)
 #include "delegation.h"
 #include "internal.h"
 
-static struct nfs_delegation *nfs_alloc_delegation(void)
-{
-       return (struct nfs_delegation *)kmalloc(sizeof(struct nfs_delegation), GFP_KERNEL);
-}
-
 static void nfs_free_delegation(struct nfs_delegation *delegation)
 {
        if (delegation->cred)
@@ -124,7 +119,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
        if ((nfsi->cache_validity & (NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_ATTR)))
                __nfs_revalidate_inode(NFS_SERVER(inode), inode);
 
-       delegation = nfs_alloc_delegation();
+       delegation = kmalloc(sizeof(*delegation), GFP_KERNEL);
        if (delegation == NULL)
                return -ENOMEM;
        memcpy(delegation->stateid.data, res->delegation.data,
index 76ca1cbc38f96e418f80ff69095480cef3b7b36c..377839bed1725895cc837aa0aedbea8ba9821c61 100644 (file)
@@ -855,6 +855,5 @@ int __init nfs_init_directcache(void)
  */
 void nfs_destroy_directcache(void)
 {
-       if (kmem_cache_destroy(nfs_direct_cachep))
-               printk(KERN_INFO "nfs_direct_cache: not all structures were freed\n");
+       kmem_cache_destroy(nfs_direct_cachep);
 }
index e8c143d182c4db83a8a352a05a0f58f777b947c8..bc9376ca86cd28ea645ea38b889ac455faf0b141 100644 (file)
@@ -277,10 +277,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                         * report the blocks in 512byte units
                         */
                        inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
-                       inode->i_blksize = inode->i_sb->s_blocksize;
                } else {
                        inode->i_blocks = fattr->du.nfs2.blocks;
-                       inode->i_blksize = fattr->du.nfs2.blocksize;
                }
                nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
                nfsi->attrtimeo_timestamp = jiffies;
@@ -443,7 +441,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, str
 {
        struct nfs_open_context *ctx;
 
-       ctx = (struct nfs_open_context *)kmalloc(sizeof(*ctx), GFP_KERNEL);
+       ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
        if (ctx != NULL) {
                atomic_set(&ctx->count, 1);
                ctx->dentry = dget(dentry);
@@ -969,10 +967,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                 * report the blocks in 512byte units
                 */
                inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
-               inode->i_blksize = inode->i_sb->s_blocksize;
        } else {
                inode->i_blocks = fattr->du.nfs2.blocks;
-               inode->i_blksize = fattr->du.nfs2.blocksize;
        }
 
        if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
@@ -1134,8 +1130,7 @@ static int __init nfs_init_inodecache(void)
 
 static void nfs_destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(nfs_inode_cachep))
-               printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(nfs_inode_cachep);
 }
 
 /*
index 77b00684894d994cb6d38890906217fbb75be589..60408646176b9e7fdc1c9da0e7cc1c8986812024 100644 (file)
@@ -26,6 +26,11 @@ LIST_HEAD(nfs_automount_list);
 static DECLARE_WORK(nfs_automount_task, nfs_expire_automounts, &nfs_automount_list);
 int nfs_mountpoint_expiry_timeout = 500 * HZ;
 
+static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
+                                       const struct dentry *dentry,
+                                       struct nfs_fh *fh,
+                                       struct nfs_fattr *fattr);
+
 /*
  * nfs_path - reconstruct the path given an arbitrary dentry
  * @base - arbitrary string to prepend to the path
@@ -209,9 +214,10 @@ static struct vfsmount *nfs_do_clone_mount(struct nfs_server *server,
  * @fattr - attributes for new root inode
  *
  */
-struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
-               const struct dentry *dentry, struct nfs_fh *fh,
-               struct nfs_fattr *fattr)
+static struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
+                                       const struct dentry *dentry,
+                                       struct nfs_fh *fh,
+                                       struct nfs_fattr *fattr)
 {
        struct nfs_clone_mount mountdata = {
                .sb = mnt_parent->mnt_sb,
index f8688eaa0001f2f9b376ac916e6ad0683402b3f9..3b234d4601e71ac51f45e71e409526aa96fcf14d 100644 (file)
@@ -449,7 +449,7 @@ nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr
                struct nfs_fattr res;
        } *ptr;
 
-       ptr = (struct unlinkxdr *)kmalloc(sizeof(*ptr), GFP_KERNEL);
+       ptr = kmalloc(sizeof(*ptr), GFP_KERNEL);
        if (!ptr)
                return -ENOMEM;
        ptr->arg.fh = NFS_FH(dir->d_inode);
index 36e902a88ca1b92bd9e81cee86317fa18a427d63..829af323f28862f2218ab1d3f5163b5953f6b623 100644 (file)
@@ -392,7 +392,6 @@ int __init nfs_init_nfspagecache(void)
 
 void nfs_destroy_nfspagecache(void)
 {
-       if (kmem_cache_destroy(nfs_page_cachep))
-               printk(KERN_INFO "nfs_page: not all structures were freed\n");
+       kmem_cache_destroy(nfs_page_cachep);
 }
 
index 630e50647bbbf02c90611f4ba7d63da613ebaccc..4529cc4f3f8fe427bb6b262718213f933b7ac6a1 100644 (file)
@@ -352,7 +352,7 @@ nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dir, struct qstr *
 {
        struct nfs_diropargs    *arg;
 
-       arg = (struct nfs_diropargs *)kmalloc(sizeof(*arg), GFP_KERNEL);
+       arg = kmalloc(sizeof(*arg), GFP_KERNEL);
        if (!arg)
                return -ENOMEM;
        arg->fh = NFS_FH(dir->d_inode);
index 69f1549da2b94d0fd4b3579f985eb545a8e88ddb..c2e49c397a27186ac9ba09ebd49710bb091935e8 100644 (file)
@@ -737,6 +737,5 @@ int __init nfs_init_readpagecache(void)
 void nfs_destroy_readpagecache(void)
 {
        mempool_destroy(nfs_rdata_mempool);
-       if (kmem_cache_destroy(nfs_rdata_cachep))
-               printk(KERN_INFO "nfs_read_data: not all structures were freed\n");
+       kmem_cache_destroy(nfs_rdata_cachep);
 }
index c12effb46fe50df5ff959455de5fcb1f2c75533e..b674462793d3375cf2adab2d642a8526e956fa0d 100644 (file)
@@ -1565,7 +1565,6 @@ void nfs_destroy_writepagecache(void)
 {
        mempool_destroy(nfs_commit_mempool);
        mempool_destroy(nfs_wdata_mempool);
-       if (kmem_cache_destroy(nfs_wdata_cachep))
-               printk(KERN_INFO "nfs_write_data: not all structures were freed\n");
+       kmem_cache_destroy(nfs_wdata_cachep);
 }
 
index bea6b94781145e7707c59dcaaaabf4cb98ea8a3f..b1902ebaab4158d03cbe1482426d89de80f76fd7 100644 (file)
@@ -573,10 +573,9 @@ idmap_lookup(struct svc_rqst *rqstp,
        struct idmap_defer_req *mdr;
        int ret;
 
-       mdr = kmalloc(sizeof(*mdr), GFP_KERNEL);
+       mdr = kzalloc(sizeof(*mdr), GFP_KERNEL);
        if (!mdr)
                return -ENOMEM;
-       memset(mdr, 0, sizeof(*mdr));
        atomic_set(&mdr->count, 1);
        init_waitqueue_head(&mdr->waitq);
        mdr->req.defer = idmap_defer;
index 9daa0b9feb8d027e438ef39c846daee95cf2d6cf..ebcf226a9e4a1fb65d04baa8e6ac10dc7f845071 100644 (file)
@@ -339,8 +339,7 @@ alloc_client(struct xdr_netobj name)
 {
        struct nfs4_client *clp;
 
-       if ((clp = kmalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) {
-               memset(clp, 0, sizeof(*clp));
+       if ((clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) {
                if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) {
                        memcpy(clp->cl_name.data, name.data, name.len);
                        clp->cl_name.len = name.len;
@@ -1006,13 +1005,10 @@ alloc_init_file(struct inode *ino)
 static void
 nfsd4_free_slab(kmem_cache_t **slab)
 {
-       int status;
-
        if (*slab == NULL)
                return;
-       status = kmem_cache_destroy(*slab);
+       kmem_cache_destroy(*slab);
        *slab = NULL;
-       WARN_ON(status);
 }
 
 static void
index d1e2c6f9f05eed155e257b0524da8cc2ff5e4566..85c36b8ca452e828493fac9a2170f474e1b7e552 100644 (file)
@@ -1149,8 +1149,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
         * Allocate a buffer to store the current name being processed
         * converted to format determined by current NLS.
         */
-       name = (u8*)kmalloc(NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1,
-                       GFP_NOFS);
+       name = kmalloc(NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1, GFP_NOFS);
        if (unlikely(!name)) {
                err = -ENOMEM;
                goto err_out;
@@ -1191,7 +1190,7 @@ static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
         * map the mft record without deadlocking.
         */
        rc = le32_to_cpu(ctx->attr->data.resident.value_length);
-       ir = (INDEX_ROOT*)kmalloc(rc, GFP_NOFS);
+       ir = kmalloc(rc, GFP_NOFS);
        if (unlikely(!ir)) {
                err = -ENOMEM;
                goto err_out;
index d313f356e66a9b8925ae75161cf182da08e79133..933dbd89c2a433275c2cdd354ef42296c54be8c8 100644 (file)
@@ -137,7 +137,7 @@ static int ntfs_init_locked_inode(struct inode *vi, ntfs_attr *na)
 
                BUG_ON(!na->name);
                i = na->name_len * sizeof(ntfschar);
-               ni->name = (ntfschar*)kmalloc(i + sizeof(ntfschar), GFP_ATOMIC);
+               ni->name = kmalloc(i + sizeof(ntfschar), GFP_ATOMIC);
                if (!ni->name)
                        return -ENOMEM;
                memcpy(ni->name, na->name, i);
@@ -556,8 +556,6 @@ static int ntfs_read_locked_inode(struct inode *vi)
 
        /* Setup the generic vfs inode parts now. */
 
-       /* This is the optimal IO size (for stat), not the fs block size. */
-       vi->i_blksize = PAGE_CACHE_SIZE;
        /*
         * This is for checking whether an inode has changed w.r.t. a file so
         * that the file can be updated if necessary (compare with f_version).
@@ -1234,7 +1232,6 @@ static int ntfs_read_locked_attr_inode(struct inode *base_vi, struct inode *vi)
        base_ni = NTFS_I(base_vi);
 
        /* Just mirror the values from the base inode. */
-       vi->i_blksize   = base_vi->i_blksize;
        vi->i_version   = base_vi->i_version;
        vi->i_uid       = base_vi->i_uid;
        vi->i_gid       = base_vi->i_gid;
@@ -1504,7 +1501,6 @@ static int ntfs_read_locked_index_inode(struct inode *base_vi, struct inode *vi)
        ni      = NTFS_I(vi);
        base_ni = NTFS_I(base_vi);
        /* Just mirror the values from the base inode. */
-       vi->i_blksize   = base_vi->i_blksize;
        vi->i_version   = base_vi->i_version;
        vi->i_uid       = base_vi->i_uid;
        vi->i_gid       = base_vi->i_gid;
index 2438c00ec0cee309a7f52f23a584fbb2e1769bf1..584260fd68489a2ec49a412f0824939660872fb8 100644 (file)
@@ -331,7 +331,7 @@ map_err_out:
                ntfs_inode **tmp;
                int new_size = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *);
 
-               tmp = (ntfs_inode **)kmalloc(new_size, GFP_NOFS);
+               tmp = kmalloc(new_size, GFP_NOFS);
                if (unlikely(!tmp)) {
                        ntfs_error(base_ni->vol->sb, "Failed to allocate "
                                        "internal buffer.");
@@ -2637,11 +2637,6 @@ mft_rec_already_initialized:
                        goto undo_mftbmp_alloc;
                }
                vi->i_ino = bit;
-               /*
-                * This is the optimal IO size (for stat), not the fs block
-                * size.
-                */
-               vi->i_blksize = PAGE_CACHE_SIZE;
                /*
                 * This is for checking whether an inode has changed w.r.t. a
                 * file so that the file can be updated if necessary (compare
@@ -2893,7 +2888,7 @@ rollback:
        if (!(base_ni->nr_extents & 3)) {
                int new_size = (base_ni->nr_extents + 4) * sizeof(ntfs_inode*);
 
-               extent_nis = (ntfs_inode**)kmalloc(new_size, GFP_NOFS);
+               extent_nis = kmalloc(new_size, GFP_NOFS);
                if (unlikely(!extent_nis)) {
                        ntfs_error(vol->sb, "Failed to allocate internal "
                                        "buffer during rollback.%s", es);
index 74e0ee8fce721ec8326a090b62a4ad79cb5d0156..6b2712f10dd288d07469e6fcbbce1d8abdf1657f 100644 (file)
@@ -3248,32 +3248,14 @@ ictx_err_out:
 
 static void __exit exit_ntfs_fs(void)
 {
-       int err = 0;
-
        ntfs_debug("Unregistering NTFS driver.");
 
        unregister_filesystem(&ntfs_fs_type);
-
-       if (kmem_cache_destroy(ntfs_big_inode_cache) && (err = 1))
-               printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
-                               ntfs_big_inode_cache_name);
-       if (kmem_cache_destroy(ntfs_inode_cache) && (err = 1))
-               printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
-                               ntfs_inode_cache_name);
-       if (kmem_cache_destroy(ntfs_name_cache) && (err = 1))
-               printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
-                               ntfs_name_cache_name);
-       if (kmem_cache_destroy(ntfs_attr_ctx_cache) && (err = 1))
-               printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
-                               ntfs_attr_ctx_cache_name);
-       if (kmem_cache_destroy(ntfs_index_ctx_cache) && (err = 1))
-               printk(KERN_CRIT "NTFS: Failed to destory %s.\n",
-                               ntfs_index_ctx_cache_name);
-       if (err)
-               printk(KERN_CRIT "NTFS: This causes memory to leak! There is "
-                               "probably a BUG in the driver! Please report "
-                               "you saw this message to "
-                               "linux-ntfs-dev@lists.sourceforge.net\n");
+       kmem_cache_destroy(ntfs_big_inode_cache);
+       kmem_cache_destroy(ntfs_inode_cache);
+       kmem_cache_destroy(ntfs_name_cache);
+       kmem_cache_destroy(ntfs_attr_ctx_cache);
+       kmem_cache_destroy(ntfs_index_ctx_cache);
        /* Unregister the ntfs sysctls. */
        ntfs_sysctl(0);
 }
index b123c0fa6bf6a4d7b10ad1c7cda1dcd1ec0ddf9c..a1b572196fe4a14f86aaaeb6f0656b79d386ebf1 100644 (file)
@@ -350,7 +350,7 @@ int ntfs_ucstonls(const ntfs_volume *vol, const ntfschar *ins,
                }
                if (!ns) {
                        ns_len = ins_len * NLS_MAX_CHARSET_SIZE;
-                       ns = (unsigned char*)kmalloc(ns_len + 1, GFP_NOFS);
+                       ns = kmalloc(ns_len + 1, GFP_NOFS);
                        if (!ns)
                                goto mem_err_out;
                }
@@ -365,7 +365,7 @@ retry:                      wc = nls->uni2char(le16_to_cpu(ins[i]), ns + o,
                        else if (wc == -ENAMETOOLONG && ns != *outs) {
                                unsigned char *tc;
                                /* Grow in multiples of 64 bytes. */
-                               tc = (unsigned char*)kmalloc((ns_len + 64) &
+                               tc = kmalloc((ns_len + 64) &
                                                ~63, GFP_NOFS);
                                if (tc) {
                                        memcpy(tc, ns, ns_len);
index 033ad17012325dcc19d1bfe1f38cca44b8feeb21..0368c64021822c56f809d84cd84cdcace2ea81d4 100644 (file)
@@ -335,7 +335,6 @@ static struct inode *dlmfs_get_root_inode(struct super_block *sb)
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -362,7 +361,6 @@ static struct inode *dlmfs_get_inode(struct inode *parent,
        inode->i_mode = mode;
        inode->i_uid = current->fsuid;
        inode->i_gid = current->fsgid;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_mapping->backing_dev_info = &dlmfs_backing_dev_info;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
@@ -629,9 +627,7 @@ static void __exit exit_dlmfs_fs(void)
        flush_workqueue(user_dlm_worker);
        destroy_workqueue(user_dlm_worker);
 
-       if (kmem_cache_destroy(dlmfs_inode_cache))
-               printk(KERN_INFO "dlmfs_inode_cache: not all structures "
-                      "were freed\n");
+       kmem_cache_destroy(dlmfs_inode_cache);
 }
 
 MODULE_AUTHOR("Oracle");
index de887063dcfc7542989e2e30641d75ad963fc18d..8801e41afe8092ad9db9c8c469b5ff1cbfb94fbb 100644 (file)
@@ -2052,7 +2052,7 @@ static int ocfs2_dlm_debug_open(struct inode *inode, struct file *file)
                mlog_errno(ret);
                goto out;
        }
-       osb = (struct ocfs2_super *) inode->u.generic_ip;
+       osb = inode->i_private;
        ocfs2_get_dlm_debug(osb->osb_dlm_debug);
        priv->p_dlm_debug = osb->osb_dlm_debug;
        INIT_LIST_HEAD(&priv->p_iter_res.l_debug_list);
index 69d3db5691660a3bca977f77627abe4a46498f25..16e8e74dc966d452401d55a8381e5d89afa64737 100644 (file)
@@ -269,7 +269,6 @@ int ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
        inode->i_mode = le16_to_cpu(fe->i_mode);
        inode->i_uid = le32_to_cpu(fe->i_uid);
        inode->i_gid = le32_to_cpu(fe->i_gid);
-       inode->i_blksize = (u32)osb->s_clustersize;
 
        /* Fast symlinks will have i_size but no allocated clusters. */
        if (S_ISLNK(inode->i_mode) && !fe->i_clusters)
@@ -1258,8 +1257,6 @@ leave:
 void ocfs2_refresh_inode(struct inode *inode,
                         struct ocfs2_dinode *fe)
 {
-       struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
-
        spin_lock(&OCFS2_I(inode)->ip_lock);
 
        OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
@@ -1270,7 +1267,6 @@ void ocfs2_refresh_inode(struct inode *inode,
        inode->i_uid = le32_to_cpu(fe->i_uid);
        inode->i_gid = le32_to_cpu(fe->i_gid);
        inode->i_mode = le16_to_cpu(fe->i_mode);
-       inode->i_blksize = (u32) osb->s_clustersize;
        if (S_ISLNK(inode->i_mode) && le32_to_cpu(fe->i_clusters) == 0)
                inode->i_blocks = 0;
        else
index 63730282ad813688410809c25d22055c5cb38570..1bea610078b35c34808245cc2214947bd369d672 100644 (file)
@@ -238,10 +238,9 @@ alloc_read_gpt_entries(struct block_device *bdev, gpt_header *gpt)
                 le32_to_cpu(gpt->sizeof_partition_entry);
        if (!count)
                return NULL;
-       pte = kmalloc(count, GFP_KERNEL);
+       pte = kzalloc(count, GFP_KERNEL);
        if (!pte)
                return NULL;
-       memset(pte, 0, count);
 
        if (read_lba(bdev, le64_to_cpu(gpt->partition_entry_lba),
                      (u8 *) pte,
@@ -269,10 +268,9 @@ alloc_read_gpt_header(struct block_device *bdev, u64 lba)
        if (!bdev)
                return NULL;
 
-       gpt = kmalloc(sizeof (gpt_header), GFP_KERNEL);
+       gpt = kzalloc(sizeof (gpt_header), GFP_KERNEL);
        if (!gpt)
                return NULL;
-       memset(gpt, 0, sizeof (gpt_header));
 
        if (read_lba(bdev, lba, (u8 *) gpt,
                     sizeof (gpt_header)) < sizeof (gpt_header)) {
@@ -526,9 +524,8 @@ find_valid_gpt(struct block_device *bdev, gpt_header **gpt, gpt_entry **ptes)
        lastlba = last_lba(bdev);
         if (!force_gpt) {
                 /* This will be added to the EFI Spec. per Intel after v1.02. */
-                legacymbr = kmalloc(sizeof (*legacymbr), GFP_KERNEL);
+                legacymbr = kzalloc(sizeof (*legacymbr), GFP_KERNEL);
                 if (legacymbr) {
-                        memset(legacymbr, 0, sizeof (*legacymbr));
                         read_lba(bdev, 0, (u8 *) legacymbr,
                                  sizeof (*legacymbr));
                         good_pmbr = is_pmbr_valid(legacymbr, lastlba);
index 20352573e025f0fe2574b6ffb300c44fc3605fa9..f3b6f71e9d0bdd5680cca1d889305bd339a1d67d 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -879,7 +879,6 @@ static struct inode * get_pipe_inode(void)
        inode->i_uid = current->fsuid;
        inode->i_gid = current->fsgid;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-       inode->i_blksize = PAGE_SIZE;
 
        return inode;
 
index 146a434ba944a89aaf026094755bc3818ba146c4..987c773dbb20a04f002ac03ae5f8ee522ba57cce 100644 (file)
@@ -28,6 +28,7 @@ do {                                          \
        (vmi)->largest_chunk = 0;               \
 } while(0)
 
+extern int nommu_vma_show(struct seq_file *, struct vm_area_struct *);
 #endif
 
 extern void create_seq_entry(char *name, mode_t mode, const struct file_operations *f);
index 6a984f64edd7179893887528f07a63f90bf7b15c..3ceff385727273269018a6e4780a97a6bd234cc6 100644 (file)
@@ -279,12 +279,11 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
                tsz = elf_buflen - *fpos;
                if (buflen < tsz)
                        tsz = buflen;
-               elf_buf = kmalloc(elf_buflen, GFP_ATOMIC);
+               elf_buf = kzalloc(elf_buflen, GFP_ATOMIC);
                if (!elf_buf) {
                        read_unlock(&kclist_lock);
                        return -ENOMEM;
                }
-               memset(elf_buf, 0, elf_buflen);
                elf_kcore_store_hdr(elf_buf, nphdr, elf_buflen);
                read_unlock(&kclist_lock);
                if (copy_to_user(buffer, elf_buf + *fpos, tsz)) {
@@ -330,10 +329,9 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
                        unsigned long curstart = start;
                        unsigned long cursize = tsz;
 
-                       elf_buf = kmalloc(tsz, GFP_KERNEL);
+                       elf_buf = kzalloc(tsz, GFP_KERNEL);
                        if (!elf_buf)
                                return -ENOMEM;
-                       memset(elf_buf, 0, tsz);
 
                        read_lock(&vmlist_lock);
                        for (m=vmlist; m && cursize; m=m->next) {
index cff10ab1af630c69aa8d3a9af4f450834f120247..d7dbdf9e0f496adfa70facf0612ca382e41a3462 100644 (file)
 #include "internal.h"
 
 /*
- * display a list of all the VMAs the kernel knows about
- * - nommu kernals have a single flat list
+ * display a single VMA to a sequenced file
  */
-static int nommu_vma_list_show(struct seq_file *m, void *v)
+int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
 {
-       struct vm_area_struct *vma;
        unsigned long ino = 0;
        struct file *file;
        dev_t dev = 0;
        int flags, len;
 
-       vma = rb_entry((struct rb_node *) v, struct vm_area_struct, vm_rb);
-
        flags = vma->vm_flags;
        file = vma->vm_file;
 
@@ -78,6 +74,18 @@ static int nommu_vma_list_show(struct seq_file *m, void *v)
        return 0;
 }
 
+/*
+ * display a list of all the VMAs the kernel knows about
+ * - nommu kernals have a single flat list
+ */
+static int nommu_vma_list_show(struct seq_file *m, void *v)
+{
+       struct vm_area_struct *vma;
+
+       vma = rb_entry((struct rb_node *) v, struct vm_area_struct, vm_rb);
+       return nommu_vma_show(m, vma);
+}
+
 static void *nommu_vma_list_start(struct seq_file *m, loff_t *_pos)
 {
        struct rb_node *_rb;
index 0a163a4f7764059f7401c8b43cae42ca9c2bef43..6b769afac55a18ff274ef8ed90b2d0510a86804b 100644 (file)
@@ -122,11 +122,6 @@ struct mem_size_stats
        unsigned long private_dirty;
 };
 
-__attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma)
-{
-       return NULL;
-}
-
 static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
 {
        struct proc_maps_private *priv = m->private;
index 4616ed50ffcdea037a49111cf3d5f0d53af994c6..091aa8e48e0285f825f513a3ca9daa760edc56d6 100644 (file)
@@ -138,25 +138,63 @@ out:
 }
 
 /*
- * Albert D. Cahalan suggested to fake entries for the traditional
- * sections here.  This might be worth investigating.
+ * display mapping lines for a particular process's /proc/pid/maps
  */
-static int show_map(struct seq_file *m, void *v)
+static int show_map(struct seq_file *m, void *_vml)
 {
-       return 0;
+       struct vm_list_struct *vml = _vml;
+       return nommu_vma_show(m, vml->vma);
 }
+
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
+       struct proc_maps_private *priv = m->private;
+       struct vm_list_struct *vml;
+       struct mm_struct *mm;
+       loff_t n = *pos;
+
+       /* pin the task and mm whilst we play with them */
+       priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
+       if (!priv->task)
+               return NULL;
+
+       mm = get_task_mm(priv->task);
+       if (!mm) {
+               put_task_struct(priv->task);
+               priv->task = NULL;
+               return NULL;
+       }
+
+       down_read(&mm->mmap_sem);
+
+       /* start from the Nth VMA */
+       for (vml = mm->context.vmlist; vml; vml = vml->next)
+               if (n-- == 0)
+                       return vml;
        return NULL;
 }
-static void m_stop(struct seq_file *m, void *v)
+
+static void m_stop(struct seq_file *m, void *_vml)
 {
+       struct proc_maps_private *priv = m->private;
+
+       if (priv->task) {
+               struct mm_struct *mm = priv->task->mm;
+               up_read(&mm->mmap_sem);
+               mmput(mm);
+               put_task_struct(priv->task);
+       }
 }
-static void *m_next(struct seq_file *m, void *v, loff_t *pos)
+
+static void *m_next(struct seq_file *m, void *_vml, loff_t *pos)
 {
-       return NULL;
+       struct vm_list_struct *vml = _vml;
+
+       (*pos)++;
+       return vml ? vml->next : NULL;
 }
-static struct seq_operations proc_pid_maps_op = {
+
+static struct seq_operations proc_pid_maps_ops = {
        .start  = m_start,
        .next   = m_next,
        .stop   = m_stop,
@@ -165,11 +203,19 @@ static struct seq_operations proc_pid_maps_op = {
 
 static int maps_open(struct inode *inode, struct file *file)
 {
-       int ret;
-       ret = seq_open(file, &proc_pid_maps_op);
-       if (!ret) {
-               struct seq_file *m = file->private_data;
-               m->private = NULL;
+       struct proc_maps_private *priv;
+       int ret = -ENOMEM;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (priv) {
+               priv->pid = proc_pid(inode);
+               ret = seq_open(file, &proc_pid_maps_ops);
+               if (!ret) {
+                       struct seq_file *m = file->private_data;
+                       m->private = priv;
+               } else {
+                       kfree(priv);
+               }
        }
        return ret;
 }
@@ -178,6 +224,6 @@ struct file_operations proc_maps_operations = {
        .open           = maps_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = seq_release,
+       .release        = seq_release_private,
 };
 
index 5a903491e6972577ef38ee98a1d1c5fb1ddfc1e7..5a41db2a218dedccfad415885fd54727d0c2fade 100644 (file)
@@ -358,11 +358,10 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
        const char *errmsg;
        struct qnx4_sb_info *qs;
 
-       qs = kmalloc(sizeof(struct qnx4_sb_info), GFP_KERNEL);
+       qs = kzalloc(sizeof(struct qnx4_sb_info), GFP_KERNEL);
        if (!qs)
                return -ENOMEM;
        s->s_fs_info = qs;
-       memset(qs, 0, sizeof(struct qnx4_sb_info));
 
        sb_set_blocksize(s, QNX4_BLOCK_SIZE);
 
@@ -497,7 +496,6 @@ static void qnx4_read_inode(struct inode *inode)
        inode->i_ctime.tv_sec   = le32_to_cpu(raw_inode->di_ctime);
        inode->i_ctime.tv_nsec = 0;
        inode->i_blocks  = le32_to_cpu(raw_inode->di_first_xtnt.xtnt_size);
-       inode->i_blksize = QNX4_DIR_ENTRY_SIZE;
 
        memcpy(qnx4_inode, raw_inode, QNX4_DIR_ENTRY_SIZE);
        if (S_ISREG(inode->i_mode)) {
@@ -557,9 +555,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(qnx4_inode_cachep))
-               printk(KERN_INFO
-                      "qnx4_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(qnx4_inode_cachep);
 }
 
 static int qnx4_get_sb(struct file_system_type *fs_type,
index b9677335cc8d8c146c92daaf4e81b308a11121e8..bc0e51662424070cc1d5a38f8dcee23034a42d45 100644 (file)
@@ -58,7 +58,6 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->a_ops = &ramfs_aops;
                inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
index 52f1e2136546f215f7bd13ea403735222a621e46..8810fda0da469aa14ebf69ea51aeaedb2686e0f5 100644 (file)
@@ -17,8 +17,6 @@
 #include <linux/writeback.h>
 #include <linux/quotaops.h>
 
-extern int reiserfs_default_io_size;   /* default io size devuned in super.c */
-
 static int reiserfs_commit_write(struct file *f, struct page *page,
                                 unsigned from, unsigned to);
 static int reiserfs_prepare_write(struct file *f, struct page *page,
@@ -1122,7 +1120,6 @@ static void init_inode(struct inode *inode, struct path *path)
        ih = PATH_PITEM_HEAD(path);
 
        copy_key(INODE_PKEY(inode), &(ih->ih_key));
-       inode->i_blksize = reiserfs_default_io_size;
 
        INIT_LIST_HEAD(&(REISERFS_I(inode)->i_prealloc_list));
        REISERFS_I(inode)->i_flags = 0;
@@ -1877,7 +1874,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
        }
        // these do not go to on-disk stat data
        inode->i_ino = le32_to_cpu(ih.ih_key.k_objectid);
-       inode->i_blksize = reiserfs_default_io_size;
 
        // store in in-core inode the key of stat data and version all
        // object items will have (directory items will have old offset
index 5567328f10415c85fbbe068672ed85a5f7ad0ead..b40d4d64d598b83ce47b578ed487a7f282178605 100644 (file)
@@ -530,9 +530,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(reiserfs_inode_cachep))
-               reiserfs_warning(NULL,
-                                "reiserfs_inode_cache: not all structures were freed");
+       kmem_cache_destroy(reiserfs_inode_cachep);
 }
 
 /* we don't mark inodes dirty, we just log them */
@@ -725,12 +723,6 @@ static const arg_desc_t error_actions[] = {
        {NULL, 0, 0},
 };
 
-int reiserfs_default_io_size = 128 * 1024;     /* Default recommended I/O size is 128k.
-                                                  There might be broken applications that are
-                                                  confused by this. Use nolargeio mount option
-                                                  to get usual i/o size = PAGE_SIZE.
-                                                */
-
 /* proceed only one option from a list *cur - string containing of mount options
    opts - array of options which are accepted
    opt_arg - if option is found and requires an argument and if it is specifed
@@ -959,19 +951,8 @@ static int reiserfs_parse_options(struct super_block *s, char *options,    /* strin
                }
 
                if (c == 'w') {
-                       char *p = NULL;
-                       int val = simple_strtoul(arg, &p, 0);
-
-                       if (*p != '\0') {
-                               reiserfs_warning(s,
-                                                "reiserfs_parse_options: non-numeric value %s for nolargeio option",
-                                                arg);
-                               return 0;
-                       }
-                       if (val)
-                               reiserfs_default_io_size = PAGE_SIZE;
-                       else
-                               reiserfs_default_io_size = 128 * 1024;
+                       reiserfs_warning(s, "reiserfs: nolargeio option is no longer supported");
+                       return 0;
                }
 
                if (c == 'j') {
index 22eed61ebf693dd70c51c1bebe1938d2ffb0f528..ddcd9e1ef2828a52e91e1d5a71754509dc5f8dbb 100644 (file)
@@ -589,8 +589,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(romfs_inode_cachep))
-               printk(KERN_INFO "romfs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(romfs_inode_cachep);
 }
 
 static int romfs_remount(struct super_block *sb, int *flags, char *data)
index a1ed657c3c84323037f526cc341bb63fd44336cf..2c122ee83adbdd3d693c2c8a4fb671aeca4b85f3 100644 (file)
@@ -89,8 +89,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(smb_inode_cachep))
-               printk(KERN_INFO "smb_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(smb_inode_cachep);
 }
 
 static int smb_remount(struct super_block *sb, int *flags, char *data)
@@ -167,7 +166,6 @@ smb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr)
        fattr->f_mtime  = inode->i_mtime;
        fattr->f_ctime  = inode->i_ctime;
        fattr->f_atime  = inode->i_atime;
-       fattr->f_blksize= inode->i_blksize;
        fattr->f_blocks = inode->i_blocks;
 
        fattr->attr     = SMB_I(inode)->attr;
@@ -201,7 +199,6 @@ smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
        inode->i_uid    = fattr->f_uid;
        inode->i_gid    = fattr->f_gid;
        inode->i_ctime  = fattr->f_ctime;
-       inode->i_blksize= fattr->f_blksize;
        inode->i_blocks = fattr->f_blocks;
        inode->i_size   = fattr->f_size;
        inode->i_mtime  = fattr->f_mtime;
index c3495059889df1958ce08ad570730d4921f429ca..40e174db9872fb0a915e83ba77d0b08975a708ff 100644 (file)
@@ -1826,7 +1826,6 @@ smb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr)
        fattr->f_nlink = 1;
        fattr->f_uid = server->mnt->uid;
        fattr->f_gid = server->mnt->gid;
-       fattr->f_blksize = SMB_ST_BLKSIZE;
        fattr->f_unix = 0;
 }
 
index c8e96195b96ee29c52b931b4c2b47c9e1f90e8e0..0fb74697abc401694ea0a0e9aed4f8352a5213c5 100644 (file)
@@ -49,8 +49,7 @@ int smb_init_request_cache(void)
 
 void smb_destroy_request_cache(void)
 {
-       if (kmem_cache_destroy(req_cachep))
-               printk(KERN_INFO "smb_destroy_request_cache: not all structures were freed\n");
+       kmem_cache_destroy(req_cachep);
 }
 
 /*
index 3a44dcf97da23d1704b599527db4a50edcbc04a6..60a31d5e5966a03ba0a3e009ae521bf02ade2adb 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -14,6 +14,7 @@
 #include <linux/namei.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/pagemap.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -32,7 +33,7 @@ void generic_fillattr(struct inode *inode, struct kstat *stat)
        stat->ctime = inode->i_ctime;
        stat->size = i_size_read(inode);
        stat->blocks = inode->i_blocks;
-       stat->blksize = inode->i_blksize;
+       stat->blksize = (1 << inode->i_blkbits);
 }
 
 EXPORT_SYMBOL(generic_fillattr);
index c16a93c353c0cba3c7503b8041341be39ff69c21..98022e41cda121aa6f511538691531351e4499e1 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/errno.h>
 #include <linux/fs.h>
+#include <linux/kernel.h>
 #include <linux/kobject.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -176,7 +177,6 @@ const struct file_operations bin_fops = {
  *     sysfs_create_bin_file - create binary file for object.
  *     @kobj:  object.
  *     @attr:  attribute descriptor.
- *
  */
 
 int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
@@ -191,13 +191,16 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr)
  *     sysfs_remove_bin_file - remove binary file for object.
  *     @kobj:  object.
  *     @attr:  attribute descriptor.
- *
  */
 
-int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
+void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr)
 {
-       sysfs_hash_and_remove(kobj->dentry,attr->attr.name);
-       return 0;
+       if (sysfs_hash_and_remove(kobj->dentry, attr->attr.name) < 0) {
+               printk(KERN_ERR "%s: "
+                       "bad dentry or inode or no such file: \"%s\"\n",
+                       __FUNCTION__, attr->attr.name);
+               dump_stack();
+       }
 }
 
 EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
index 61c42430cba3159e5cce02d8675cb2d8c1bec14b..5f3d725d11251487481c57599bc0f0ddedcfe904 100644 (file)
@@ -43,7 +43,7 @@ static struct sysfs_dirent * sysfs_new_dirent(struct sysfs_dirent * parent_sd,
 
        memset(sd, 0, sizeof(*sd));
        atomic_set(&sd->s_count, 1);
-       atomic_set(&sd->s_event, 0);
+       atomic_set(&sd->s_event, 1);
        INIT_LIST_HEAD(&sd->s_children);
        list_add(&sd->s_sibling, &parent_sd->s_children);
        sd->s_element = element;
index 9889e54e1f13632e967423458cb83b4d5d590047..e79e38d52c0067185ba5fabf29a1f0c3e474172b 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/namei.h>
 #include <linux/backing-dev.h>
 #include <linux/capability.h>
+#include <linux/errno.h>
 #include "sysfs.h"
 
 extern struct super_block * sysfs_sb;
@@ -124,7 +125,6 @@ struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
 {
        struct inode * inode = new_inode(sysfs_sb);
        if (inode) {
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->a_ops = &sysfs_aops;
                inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
@@ -234,17 +234,18 @@ void sysfs_drop_dentry(struct sysfs_dirent * sd, struct dentry * parent)
        }
 }
 
-void sysfs_hash_and_remove(struct dentry * dir, const char * name)
+int sysfs_hash_and_remove(struct dentry * dir, const char * name)
 {
        struct sysfs_dirent * sd;
        struct sysfs_dirent * parent_sd;
+       int found = 0;
 
        if (!dir)
-               return;
+               return -ENOENT;
 
        if (dir->d_inode == NULL)
                /* no inode means this hasn't been made visible yet */
-               return;
+               return -ENOENT;
 
        parent_sd = dir->d_fsdata;
        mutex_lock(&dir->d_inode->i_mutex);
@@ -255,8 +256,11 @@ void sysfs_hash_and_remove(struct dentry * dir, const char * name)
                        list_del_init(&sd->s_sibling);
                        sysfs_drop_dentry(sd, dir);
                        sysfs_put(sd);
+                       found = 1;
                        break;
                }
        }
        mutex_unlock(&dir->d_inode->i_mutex);
+
+       return found ? 0 : -ENOENT;
 }
index d2eac3ceed5f31cf9735a68ecc69dc4a6c6771ed..f50e3cc2ded8d76e00d203829108b40647f1fc63 100644 (file)
@@ -3,6 +3,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/mount.h>
 #include <linux/module.h>
 #include <linux/kobject.h>
 #include <linux/namei.h>
@@ -82,10 +83,19 @@ exit1:
  */
 int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
 {
-       struct dentry * dentry = kobj->dentry;
+       struct dentry *dentry = NULL;
        int error = -EEXIST;
 
-       BUG_ON(!kobj || !kobj->dentry || !name);
+       BUG_ON(!name);
+
+       if (!kobj) {
+               if (sysfs_mount && sysfs_mount->mnt_sb)
+                       dentry = sysfs_mount->mnt_sb->s_root;
+       } else
+               dentry = kobj->dentry;
+
+       if (!dentry)
+               return -EFAULT;
 
        mutex_lock(&dentry->d_inode->i_mutex);
        if (!sysfs_dirent_exist(dentry->d_fsdata, name))
index 3651ffb5ec091972f92f418dce997883feae6f40..6f3d6bd52887bcd541aa917ede96338d47300bfe 100644 (file)
@@ -10,7 +10,7 @@ extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
                                umode_t, int);
 
 extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
-extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
+extern int sysfs_hash_and_remove(struct dentry * dir, const char * name);
 extern struct sysfs_dirent *sysfs_find(struct sysfs_dirent *dir, const char * name);
 
 extern int sysfs_create_subdir(struct kobject *, const char *, struct dentry **);
index 9b585d1081c0d142664e064f82c5a5669ea4d2ca..115ab0d6f4bcab86b06243cd107f92c082285c00 100644 (file)
@@ -170,7 +170,7 @@ struct inode * sysv_new_inode(const struct inode * dir, mode_t mode)
        inode->i_uid = current->fsuid;
        inode->i_ino = fs16_to_cpu(sbi, ino);
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
        memset(SYSV_I(inode)->i_data, 0, sizeof(SYSV_I(inode)->i_data));
        SYSV_I(inode)->i_dir_start_lookup = 0;
        insert_inode_hash(inode);
index 58b2d22142ba67dc81aa8d9bff0f909808d4c250..d63c5e48b050e0865c19d086e9e6346fc59a8f47 100644 (file)
@@ -201,7 +201,7 @@ static void sysv_read_inode(struct inode *inode)
        inode->i_ctime.tv_nsec = 0;
        inode->i_atime.tv_nsec = 0;
        inode->i_mtime.tv_nsec = 0;
-       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_blocks = 0;
 
        si = SYSV_I(inode);
        for (block = 0; block < 10+1+1+1; block++)
index 876639b93321b42ac37336fa6a336ca6bb946a56..350cba5d68034f8dd4bdbb2732e2d5bc0cc17f9a 100644 (file)
@@ -369,10 +369,9 @@ static int sysv_fill_super(struct super_block *sb, void *data, int silent)
        if (64 != sizeof (struct sysv_inode))
                panic("sysv fs: bad inode size");
 
-       sbi = kmalloc(sizeof(struct sysv_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct sysv_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
-       memset(sbi, 0, sizeof(struct sysv_sb_info));
 
        sbi->s_sb = sb;
        sbi->s_block_base = 0;
@@ -453,10 +452,9 @@ static int v7_fill_super(struct super_block *sb, void *data, int silent)
        if (64 != sizeof (struct sysv_inode))
                panic("sysv fs: bad i-node size");
 
-       sbi = kmalloc(sizeof(struct sysv_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct sysv_sb_info), GFP_KERNEL);
        if (!sbi)
                return -ENOMEM;
-       memset(sbi, 0, sizeof(struct sysv_sb_info));
 
        sbi->s_sb = sb;
        sbi->s_block_base = 0;
index 33323473e3c43edfbd53a16014f3bf313d580ac4..8206983f2ebf924c1bf91629206fbc518d014c69 100644 (file)
@@ -121,7 +121,6 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
        UDF_I_LOCATION(inode).logicalBlockNum = block;
        UDF_I_LOCATION(inode).partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
        inode->i_ino = udf_get_lb_pblock(sb, UDF_I_LOCATION(inode), 0);
-       inode->i_blksize = PAGE_SIZE;
        inode->i_blocks = 0;
        UDF_I_LENEATTR(inode) = 0;
        UDF_I_LENALLOC(inode) = 0;
@@ -130,14 +129,12 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
        {
                UDF_I_EFE(inode) = 1;
                UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
-               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
-               memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
+               UDF_I_DATA(inode) = kzalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
        }
        else
        {
                UDF_I_EFE(inode) = 0;
-               UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
-               memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct fileEntry));
+               UDF_I_DATA(inode) = kzalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
        }
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
                UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
index 605f5111b6d86a100430897877f170c2b59248e7..b223b32db991c4a1d3b4dbb225e0217733ec4dcd 100644 (file)
@@ -916,8 +916,6 @@ __udf_read_inode(struct inode *inode)
         *      i_nlink = 1
         *      i_op = NULL;
         */
-       inode->i_blksize = PAGE_SIZE;
-
        bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
 
        if (!bh)
index fcce1a21a51bdc1c0a095ccc815d35bd6399bf0f..5dd356cbbda607de674b825d40ecf0c72fce490b 100644 (file)
@@ -156,8 +156,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(udf_inode_cachep))
-               printk(KERN_INFO "udf_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(udf_inode_cachep);
 }
 
 /* Superblock operations */
index 9501dcd3b2132b4c0235fd0e187cb11648fc0708..2ad1259c6ecaacd7f6130859c42cb8654fb0e991 100644 (file)
@@ -255,7 +255,6 @@ cg_found:
                inode->i_gid = current->fsgid;
 
        inode->i_ino = cg * uspi->s_ipg + bit;
-       inode->i_blksize = PAGE_SIZE;   /* This is the optimal IO size (for stat), not the fs block size */
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
        ufsi->i_flags = UFS_I(dir)->i_flags;
index 30c6e8a9446c20382147423d97cc77af2a4ac137..ee1eaa6f4ec2187f0f669324d2aaa7253932318a 100644 (file)
@@ -741,7 +741,6 @@ void ufs_read_inode(struct inode * inode)
                ufs1_read_inode(inode, ufs_inode + ufs_inotofsbo(inode->i_ino));
        }
 
-       inode->i_blksize = PAGE_SIZE;/*This is the optimal IO size (for stat)*/
        inode->i_version++;
        ufsi->i_lastfrag =
                (inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift;
index 992ee0b87cc3f7835fa376c75733822d9ddfbdc6..ec79e3091d1bc7f647905edc7c410c94dcb10a3a 100644 (file)
@@ -611,11 +611,10 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
        
        UFSD("ENTER\n");
                
-       sbi = kmalloc(sizeof(struct ufs_sb_info), GFP_KERNEL);
+       sbi = kzalloc(sizeof(struct ufs_sb_info), GFP_KERNEL);
        if (!sbi)
                goto failed_nomem;
        sb->s_fs_info = sbi;
-       memset(sbi, 0, sizeof(struct ufs_sb_info));
 
        UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY));
        
@@ -1245,8 +1244,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(ufs_inode_cachep))
-               printk(KERN_INFO "ufs_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(ufs_inode_cachep);
 }
 
 #ifdef CONFIG_QUOTA
index 939bd84bc7ee3c0b137ad10a0353883e03f82946..0e8293c5a32fb9ac8c00d9481627f7d20580dfae 100644 (file)
@@ -91,8 +91,8 @@ kmem_zone_free(kmem_zone_t *zone, void *ptr)
 static inline void
 kmem_zone_destroy(kmem_zone_t *zone)
 {
-       if (zone && kmem_cache_destroy(zone))
-               BUG();
+       if (zone)
+               kmem_cache_destroy(zone);
 }
 
 extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast);
index 3d4f6dff21134a26b622d4450b0e763906ccba1e..41cfcba7ce49bed9c85e94785c163922e44a57c8 100644 (file)
@@ -370,7 +370,7 @@ xfs_file_readdir(
 
        /* Try fairly hard to get memory */
        do {
-               if ((read_buf = (caddr_t)kmalloc(rlen, GFP_KERNEL)))
+               if ((read_buf = kmalloc(rlen, GFP_KERNEL)))
                        break;
                rlen >>= 1;
        } while (rlen >= 1024);
index d9180020de6328fa8dbbeb17f68027805d368fae..22e3b714f62973a62817f1ee7262c72c387a152a 100644 (file)
@@ -553,13 +553,13 @@ xfs_vn_follow_link(
        ASSERT(dentry);
        ASSERT(nd);
 
-       link = (char *)kmalloc(MAXPATHLEN+1, GFP_KERNEL);
+       link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
        if (!link) {
                nd_set_link(nd, ERR_PTR(-ENOMEM));
                return NULL;
        }
 
-       uio = (uio_t *)kmalloc(sizeof(uio_t), GFP_KERNEL);
+       uio = kmalloc(sizeof(uio_t), GFP_KERNEL);
        if (!uio) {
                kfree(link);
                nd_set_link(nd, ERR_PTR(-ENOMEM));
index 4754f342a5d3b0cf8f9f57790fa63ed1012ee92a..9df9ed37d219fb7269932d72208d4961101c17d6 100644 (file)
@@ -171,7 +171,6 @@ xfs_revalidate_inode(
                break;
        }
 
-       inode->i_blksize = xfs_preferred_iosize(mp);
        inode->i_generation = ip->i_d.di_gen;
        i_size_write(inode, ip->i_d.di_size);
        inode->i_blocks =
index 6628d96b6fd6a02cfba135c50976ff154def34bc..553fa731ade5e5320a5cf85d73450ef5b10c69f1 100644 (file)
@@ -122,7 +122,6 @@ vn_revalidate_core(
        inode->i_blocks     = vap->va_nblocks;
        inode->i_mtime      = vap->va_mtime;
        inode->i_ctime      = vap->va_ctime;
-       inode->i_blksize    = vap->va_blocksize;
        if (vap->va_xflags & XFS_XFLAG_IMMUTABLE)
                inode->i_flags |= S_IMMUTABLE;
        else
index 30548a30c773e1685c97c08e53f63ad4bff9f385..121cd241115d33c1e22745d8fc3b1b36c0055db6 100644 (file)
@@ -12,6 +12,14 @@ struct pxa2xx_udc_mach_info {
         void (*udc_command)(int cmd);
 #define        PXA2XX_UDC_CMD_CONNECT          0       /* let host see us */
 #define        PXA2XX_UDC_CMD_DISCONNECT       1       /* so host won't see us */
+
+       /* Boards following the design guidelines in the developer's manual,
+        * with on-chip GPIOs not Lubbock's wierd hardware, can have a sane
+        * VBUS IRQ and omit the methods above.  Store the GPIO number
+        * here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits.
+        */
+       u16     gpio_vbus;                      /* high == vbus present */
+       u16     gpio_pullup;                    /* high == pullup activated */
 };
 
 extern void pxa_set_udc_info(struct pxa2xx_udc_mach_info *info);
index 1e891f860ef3ef4f430d6757dc7c6786977de882..2ab4078334bf1ee57afba6e6ffa7639903dd6889 100644 (file)
 #endif
 
 #ifdef __KERNEL__
+#include <linux/err.h>
 #include <linux/linkage.h>
 
 #define __sys2(x) #x
 
 #define __syscall_return(type, res)                                    \
 do {                                                                   \
-       if ((unsigned long)(res) >= (unsigned long)(-129)) {            \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) {      \
                errno = -(res);                                         \
                res = -1;                                               \
        }                                                               \
index 70eb6d91cfd0c85448477479fa0d2fca848dfaf9..c6d2436c9d349ca322790a81fe95181988641da0 100644 (file)
 #define __ARM_NR_usr26                 (__ARM_NR_BASE+3)
 
 #ifdef __KERNEL__
+#include <linux/err.h>
 #include <linux/linkage.h>
 
 #define __sys2(x) #x
 
 #define __syscall_return(type, res)                                    \
 do {                                                                   \
-       if ((unsigned long)(res) >= (unsigned long)(-125)) {            \
+       if ((unsigned long)(res) >= (unsigned long)-MAX_ERRNO) {        \
                errno = -(res);                                         \
                res = -1;                                               \
        }                                                               \
index b80dbd839475677b1c5721a9d5033875ee20770d..d104d1b91d399bb4f34f627b478f8740ebbee662 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls 310
+#include <linux/err.h>
 
 /*
  * process the return value of a syscall, consigning it to one of two possible fates
 #define __syscall_return(type, res)                                    \
 do {                                                                   \
         unsigned long __sr2 = (res);                                   \
-       if (__builtin_expect(__sr2 >= (unsigned long)(-4095), 0)) {     \
+       if (__builtin_expect(__sr2 >= (unsigned long)(-MAX_ERRNO), 0)) { \
                errno = (-__sr2);                                       \
                __sr2 = ~0UL;                                           \
        }                                                               \
index 253ae1328271090b4a7d94853673e93f38800d1c..69240b52f8e17931d939c96c6c2901978717b9b9 100644 (file)
         __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) {        \
                *(__ksymtab_strings)                                    \
        }                                                               \
-       __end_rodata = .;                                               \
-       . = ALIGN(4096);                                                \
                                                                        \
        /* Built-in module parameters. */                               \
        __param : AT(ADDR(__param) - LOAD_OFFSET) {                     \
                VMLINUX_SYMBOL(__start___param) = .;                    \
                *(__param)                                              \
                VMLINUX_SYMBOL(__stop___param) = .;                     \
-       }
+       }                                                               \
+       __end_rodata = .;                                               \
+       . = ALIGN(4096);
 
 #define SECURITY_INIT                                                  \
        .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
index 226dd596c2dad0de1e22943ba1853610c7c8cb20..a2dd90462d80f172b17760b1501dfd6c91e3030d 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls 289
+#include <linux/err.h>
 
-
-/* user-visible error numbers are in the range -1 - -122: see
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see
    <asm-m68k/errno.h> */
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
        /* avoid using res which is declared to be in register d0; \
           errno might expand to a function call and clobber it.  */ \
                int __err = -(res); \
index 20f52395421877301bdcc0203d4095dc378c8563..6016632d032f745106ec8cf08ab99ff0a3c90559 100644 (file)
@@ -131,21 +131,7 @@ static inline void disable_acpi(void)
 extern int acpi_gsi_to_irq(u32 gsi, unsigned int *irq);
 
 #ifdef CONFIG_X86_IO_APIC
-extern int skip_ioapic_setup;
 extern int acpi_skip_timer_override;
-
-static inline void disable_ioapic_setup(void)
-{
-       skip_ioapic_setup = 1;
-}
-
-static inline int ioapic_setup_disabled(void)
-{
-       return skip_ioapic_setup;
-}
-
-#else
-static inline void disable_ioapic_setup(void) { }
 #endif
 
 static inline void acpi_noirq_set(void) { acpi_noirq = 1; }
diff --git a/include/asm-i386/alternative-asm.i b/include/asm-i386/alternative-asm.i
new file mode 100644 (file)
index 0000000..6c47e3b
--- /dev/null
@@ -0,0 +1,14 @@
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+       .macro LOCK_PREFIX
+1:     lock
+       .section .smp_locks,"a"
+       .align 4
+       .long 1b
+       .previous
+       .endm
+#else
+       .macro LOCK_PREFIX
+       .endm
+#endif
index 2c1e371cebb6beb318b1aca3743603541ec732dc..3a42b7d6fc92ac916608c31c7fc7c3ffd3fdbd4c 100644 (file)
 #define APIC_VERBOSE 1
 #define APIC_DEBUG   2
 
-extern int enable_local_apic;
 extern int apic_verbosity;
 
-static inline void lapic_disable(void)
-{
-       enable_local_apic = -1;
-       clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-}
-
-static inline void lapic_enable(void)
-{
-       enable_local_apic = 1;
-}
-
 /*
  * Define the default level of output to be very little
  * This can be turned up by using apic=verbose for more
@@ -42,6 +30,8 @@ static inline void lapic_enable(void)
        } while (0)
 
 
+extern void generic_apic_probe(void);
+
 #ifdef CONFIG_X86_LOCAL_APIC
 
 /*
@@ -117,8 +107,6 @@ extern void enable_APIC_timer(void);
 
 extern void enable_NMI_through_LVT0 (void * dummy);
 
-extern int disable_timer_pin_1;
-
 void smp_send_timer_broadcast_ipi(struct pt_regs *regs);
 void switch_APIC_timer_to_ipi(void *cpumask);
 void switch_ipi_to_APIC_timer(void *cpumask);
index 89b8b82c82b30bb50695a3d1e63e38324444d31f..5874ef119ffdc0cf42886585c2c8aed229cfb91e 100644 (file)
@@ -33,50 +33,99 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
        return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
 }
 
+/*
+ * This is the ldt that every process will get unless we need
+ * something other than this.
+ */
+extern struct desc_struct default_ldt[];
+extern struct desc_struct idt_table[];
+extern void set_intr_gate(unsigned int irq, void * addr);
+
+static inline void pack_descriptor(__u32 *a, __u32 *b,
+       unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
+{
+       *a = ((base & 0xffff) << 16) | (limit & 0xffff);
+       *b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+               (limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
+}
+
+static inline void pack_gate(__u32 *a, __u32 *b,
+       unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
+{
+       *a = (seg << 16) | (base & 0xffff);
+       *b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
+}
+
+#define DESCTYPE_LDT   0x82    /* present, system, DPL-0, LDT */
+#define DESCTYPE_TSS   0x89    /* present, system, DPL-0, 32-bit TSS */
+#define DESCTYPE_TASK  0x85    /* present, system, DPL-0, task gate */
+#define DESCTYPE_INT   0x8e    /* present, system, DPL-0, interrupt gate */
+#define DESCTYPE_TRAP  0x8f    /* present, system, DPL-0, trap gate */
+#define DESCTYPE_DPL3  0x60    /* DPL-3 */
+#define DESCTYPE_S     0x10    /* !system */
+
 #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
 #define load_LDT_desc() __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8))
 
 #define load_gdt(dtr) __asm__ __volatile("lgdt %0"::"m" (*dtr))
 #define load_idt(dtr) __asm__ __volatile("lidt %0"::"m" (*dtr))
-#define load_tr(tr) __asm__ __volatile("ltr %0"::"mr" (tr))
-#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"mr" (ldt))
+#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
+#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
 
 #define store_gdt(dtr) __asm__ ("sgdt %0":"=m" (*dtr))
 #define store_idt(dtr) __asm__ ("sidt %0":"=m" (*dtr))
-#define store_tr(tr) __asm__ ("str %0":"=mr" (tr))
-#define store_ldt(ldt) __asm__ ("sldt %0":"=mr" (ldt))
+#define store_tr(tr) __asm__ ("str %0":"=m" (tr))
+#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
 
-/*
- * This is the ldt that every process will get unless we need
- * something other than this.
- */
-extern struct desc_struct default_ldt[];
-extern void set_intr_gate(unsigned int irq, void * addr);
+#if TLS_SIZE != 24
+# error update this code.
+#endif
 
-#define _set_tssldt_desc(n,addr,limit,type) \
-__asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
-       "movw %w1,2(%2)\n\t" \
-       "rorl $16,%1\n\t" \
-       "movb %b1,4(%2)\n\t" \
-       "movb %4,5(%2)\n\t" \
-       "movb $0,6(%2)\n\t" \
-       "movb %h1,7(%2)\n\t" \
-       "rorl $16,%1" \
-       : "=m"(*(n)) : "q" (addr), "r"(n), "ir"(limit), "i"(type))
-
-static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
+static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
 {
-       _set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr,
-               offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
+#define C(i) get_cpu_gdt_table(cpu)[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]
+       C(0); C(1); C(2);
+#undef C
 }
 
-#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
+static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b)
+{
+       __u32 *lp = (__u32 *)((char *)dt + entry*8);
+       *lp = entry_a;
+       *(lp+1) = entry_b;
+}
+
+#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+
+static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
+{
+       __u32 a, b;
+       pack_gate(&a, &b, (unsigned long)addr, seg, type, 0);
+       write_idt_entry(idt_table, gate, a, b);
+}
 
-static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
+static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
 {
-       _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
+       __u32 a, b;
+       pack_descriptor(&a, &b, (unsigned long)addr,
+                       offsetof(struct tss_struct, __cacheline_filler) - 1,
+                       DESCTYPE_TSS, 0);
+       write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b);
 }
 
+static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int entries)
+{
+       __u32 a, b;
+       pack_descriptor(&a, &b, (unsigned long)addr,
+                       entries * sizeof(struct desc_struct) - 1,
+                       DESCTYPE_LDT, 0);
+       write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b);
+}
+
+#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
+
 #define LDT_entry_a(info) \
        ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
 
@@ -102,24 +151,6 @@ static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
        (info)->seg_not_present == 1    && \
        (info)->useable         == 0    )
 
-static inline void write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b)
-{
-       __u32 *lp = (__u32 *)((char *)ldt + entry*8);
-       *lp = entry_a;
-       *(lp+1) = entry_b;
-}
-
-#if TLS_SIZE != 24
-# error update this code.
-#endif
-
-static inline void 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);
-#undef C
-}
-
 static inline void clear_LDT(void)
 {
        int cpu = get_cpu();
index 2280f6272f80c9c6e83248b72588938de6ab34de..6d66398a307d1dc16d271ec66d96fccbe949118f 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _DWARF2_H
 #define _DWARF2_H
 
-#include <linux/config.h>
-
 #ifndef __ASSEMBLY__
 #warning "asm/dwarf2.h should be only included in pure assembly files"
 #endif
 #define CFI_RESTORE .cfi_restore
 #define CFI_REMEMBER_STATE .cfi_remember_state
 #define CFI_RESTORE_STATE .cfi_restore_state
+#define CFI_UNDEFINED .cfi_undefined
+
+#ifdef CONFIG_AS_CFI_SIGNAL_FRAME
+#define CFI_SIGNAL_FRAME .cfi_signal_frame
+#else
+#define CFI_SIGNAL_FRAME
+#endif
 
 #else
 
@@ -48,6 +53,8 @@
 #define CFI_RESTORE    ignore
 #define CFI_REMEMBER_STATE ignore
 #define CFI_RESTORE_STATE ignore
+#define CFI_UNDEFINED ignore
+#define CFI_SIGNAL_FRAME ignore
 
 #endif
 
index ca82acb8cb1f7831d10bdc5fb135be8e85bf411a..f7514fb6e8e48d5deef18e316823bf95815922b2 100644 (file)
@@ -18,7 +18,7 @@
 
 #define E820_RAM       1
 #define E820_RESERVED  2
-#define E820_ACPI      3 /* usable as RAM once ACPI tables have been read */
+#define E820_ACPI      3
 #define E820_NVS       4
 
 #define HIGH_MEMORY    (1024*1024)
diff --git a/include/asm-i386/frame.i b/include/asm-i386/frame.i
new file mode 100644 (file)
index 0000000..4d68ddc
--- /dev/null
@@ -0,0 +1,24 @@
+#include <linux/config.h>
+#include <asm/dwarf2.h>
+
+/* The annotation hides the frame from the unwinder and makes it look
+   like a ordinary ebp save/restore. This avoids some special cases for
+   frame pointer later */
+#ifdef CONFIG_FRAME_POINTER
+       .macro FRAME
+       pushl %ebp
+       CFI_ADJUST_CFA_OFFSET 4
+       CFI_REL_OFFSET ebp,0
+       movl %esp,%ebp
+       .endm
+       .macro ENDFRAME
+       popl %ebp
+       CFI_ADJUST_CFA_OFFSET -4
+       CFI_RESTORE ebp
+       .endm
+#else
+       .macro FRAME
+       .endm
+       .macro ENDFRAME
+       .endm
+#endif
index b3783a32abeec92e8632465031cbca1778855351..8ffbb0f0745760f7747d850faf89d884c4cd93eb 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENAPIC_H
 #define _ASM_GENAPIC_H 1
 
+#include <asm/mpspec.h>
+
 /*
  * Generic APIC driver interface.
  *
@@ -63,14 +65,25 @@ struct genapic {
        unsigned (*get_apic_id)(unsigned long x);
        unsigned long apic_id_mask;
        unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask);
-       
+
+#ifdef CONFIG_SMP
        /* ipi */
        void (*send_IPI_mask)(cpumask_t mask, int vector);
        void (*send_IPI_allbutself)(int vector);
        void (*send_IPI_all)(int vector);
+#endif
 }; 
 
-#define APICFUNC(x) .x = x
+#define APICFUNC(x) .x = x,
+
+/* More functions could be probably marked IPIFUNC and save some space
+   in UP GENERICARCH kernels, but I don't have the nerve right now
+   to untangle this mess. -AK  */
+#ifdef CONFIG_SMP
+#define IPIFUNC(x) APICFUNC(x)
+#else
+#define IPIFUNC(x)
+#endif
 
 #define APIC_INIT(aname, aprobe) { \
        .name = aname, \
@@ -80,33 +93,33 @@ struct genapic {
        .no_balance_irq = NO_BALANCE_IRQ, \
        .ESR_DISABLE = esr_disable, \
        .apic_destination_logical = APIC_DEST_LOGICAL, \
-       APICFUNC(apic_id_registered), \
-       APICFUNC(target_cpus), \
-       APICFUNC(check_apicid_used), \
-       APICFUNC(check_apicid_present), \
-       APICFUNC(init_apic_ldr), \
-       APICFUNC(ioapic_phys_id_map), \
-       APICFUNC(clustered_apic_check), \
-       APICFUNC(multi_timer_check), \
-       APICFUNC(apicid_to_node), \
-       APICFUNC(cpu_to_logical_apicid), \
-       APICFUNC(cpu_present_to_apicid), \
-       APICFUNC(apicid_to_cpu_present), \
-       APICFUNC(mpc_apic_id), \
-       APICFUNC(setup_portio_remap), \
-       APICFUNC(check_phys_apicid_present), \
-       APICFUNC(mpc_oem_bus_info), \
-       APICFUNC(mpc_oem_pci_bus), \
-       APICFUNC(mps_oem_check), \
-       APICFUNC(get_apic_id), \
+       APICFUNC(apic_id_registered) \
+       APICFUNC(target_cpus) \
+       APICFUNC(check_apicid_used) \
+       APICFUNC(check_apicid_present) \
+       APICFUNC(init_apic_ldr) \
+       APICFUNC(ioapic_phys_id_map) \
+       APICFUNC(clustered_apic_check) \
+       APICFUNC(multi_timer_check) \
+       APICFUNC(apicid_to_node) \
+       APICFUNC(cpu_to_logical_apicid) \
+       APICFUNC(cpu_present_to_apicid) \
+       APICFUNC(apicid_to_cpu_present) \
+       APICFUNC(mpc_apic_id) \
+       APICFUNC(setup_portio_remap) \
+       APICFUNC(check_phys_apicid_present) \
+       APICFUNC(mpc_oem_bus_info) \
+       APICFUNC(mpc_oem_pci_bus) \
+       APICFUNC(mps_oem_check) \
+       APICFUNC(get_apic_id) \
        .apic_id_mask = APIC_ID_MASK, \
-       APICFUNC(cpu_mask_to_apicid), \
-       APICFUNC(acpi_madt_oem_check), \
-       APICFUNC(send_IPI_mask), \
-       APICFUNC(send_IPI_allbutself), \
-       APICFUNC(send_IPI_all), \
-       APICFUNC(enable_apic_mode), \
-       APICFUNC(phys_pkg_id), \
+       APICFUNC(cpu_mask_to_apicid) \
+       APICFUNC(acpi_madt_oem_check) \
+       IPIFUNC(send_IPI_mask) \
+       IPIFUNC(send_IPI_allbutself) \
+       IPIFUNC(send_IPI_all) \
+       APICFUNC(enable_apic_mode) \
+       APICFUNC(phys_pkg_id) \
        }
 
 extern struct genapic *genapic;
index 134ea9cc5283db8ae6c266fae8cd0c19833748ed..b52cd60a075b827ee31365873304cc053a0d00a1 100644 (file)
 
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL  (0x3c)
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK        (0x00 << 8)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT (1 << 0)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX (0)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
+                               (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
+
+union cpuid10_eax {
+       struct {
+               unsigned int version_id:8;
+               unsigned int num_counters:8;
+               unsigned int bit_width:8;
+               unsigned int mask_length:8;
+       } split;
+       unsigned int full;
+};
 
 #endif /* X86_INTEL_ARCH_PERFMON_H */
index 5092e819b8a2b23c336a79840e8ca2a955599c4a..5d309275a1dc13aef51ab44383c6edd98081b99a 100644 (file)
@@ -188,6 +188,16 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned
 /* 1 if "noapic" boot option passed */
 extern int skip_ioapic_setup;
 
+static inline void disable_ioapic_setup(void)
+{
+       skip_ioapic_setup = 1;
+}
+
+static inline int ioapic_setup_disabled(void)
+{
+       return skip_ioapic_setup;
+}
+
 /*
  * If we use the IO-APIC for IRQ routing, disable automatic
  * assignment of PCI IRQ's.
@@ -206,6 +216,7 @@ extern int (*ioapic_renumber_irq)(int ioapic, int irq);
 
 #else  /* !CONFIG_X86_IO_APIC */
 #define io_apic_assign_pci_irqs 0
+static inline void disable_ioapic_setup(void) { }
 #endif
 
 extern int assign_irq_vector(int irq);
index 53f0e06672dc1487c8ca22aff551e6ce111edcb6..4dfc9f5ed0311ede90ea8b0234f90745cfa444ce 100644 (file)
@@ -1,6 +1,26 @@
 #ifndef _I386_KEXEC_H
 #define _I386_KEXEC_H
 
+#define PA_CONTROL_PAGE  0
+#define VA_CONTROL_PAGE  1
+#define PA_PGD           2
+#define VA_PGD           3
+#define PA_PTE_0         4
+#define VA_PTE_0         5
+#define PA_PTE_1         6
+#define VA_PTE_1         7
+#ifdef CONFIG_X86_PAE
+#define PA_PMD_0         8
+#define VA_PMD_0         9
+#define PA_PMD_1         10
+#define VA_PMD_1         11
+#define PAGES_NR         12
+#else
+#define PAGES_NR         8
+#endif
+
+#ifndef __ASSEMBLY__
+
 #include <asm/fixmap.h>
 #include <asm/ptrace.h>
 #include <asm/string.h>
@@ -72,5 +92,12 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
                newregs->eip = (unsigned long)current_text_addr();
        }
 }
+asmlinkage NORET_TYPE void
+relocate_kernel(unsigned long indirection_page,
+               unsigned long control_page,
+               unsigned long start_address,
+               unsigned int has_pae) ATTRIB_NORET;
+
+#endif /* __ASSEMBLY__ */
 
 #endif /* _I386_KEXEC_H */
index b5f3f0d0b2bcc1f4573e5652837ff2b7009f9040..26333685a7fbe50974475026bced9b4ae9c13ca8 100644 (file)
@@ -123,9 +123,13 @@ extern u8 cpu_2_logical_apicid[];
 /* Mapping from cpu number to logical apicid */
 static inline int cpu_to_logical_apicid(int cpu)
 {
+#ifdef CONFIG_SMP
        if (cpu >= NR_CPUS)
               return BAD_APICID;
        return (int)cpu_2_logical_apicid[cpu];
+#else
+       return logical_smp_processor_id();
+#endif
 }
 
 static inline int mpc_apic_id(struct mpc_config_processor *m, struct mpc_config_translation *unused)
index 9fd0732862895fc4bf002765655fe329aef53ff8..a81b0596159508618a3e2b2bfc11ea5b9d62fe47 100644 (file)
@@ -46,10 +46,12 @@ extern u8 cpu_2_logical_apicid[];
 static inline void init_apic_ldr(void)
 {
        unsigned long val, id;
-       int i, count;
-       u8 lid;
+       int count = 0;
        u8 my_id = (u8)hard_smp_processor_id();
        u8 my_cluster = (u8)apicid_cluster(my_id);
+#ifdef CONFIG_SMP
+       u8 lid;
+       int i;
 
        /* Create logical APIC IDs by counting CPUs already in cluster. */
        for (count = 0, i = NR_CPUS; --i >= 0; ) {
@@ -57,6 +59,7 @@ static inline void init_apic_ldr(void)
                if (lid != BAD_APICID && apicid_cluster(lid) == my_cluster)
                        ++count;
        }
+#endif
        /* We only have a 4 wide bitmap in cluster mode.  If a deranged
         * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */
        BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT);
@@ -91,9 +94,13 @@ static inline int apicid_to_node(int logical_apicid)
 /* Mapping from cpu number to logical apicid */
 static inline int cpu_to_logical_apicid(int cpu)
 {
+#ifdef CONFIG_SMP
        if (cpu >= NR_CPUS)
               return BAD_APICID;
        return (int)cpu_2_logical_apicid[cpu];
+#else
+       return logical_smp_processor_id();
+#endif
 }
 
 static inline int cpu_present_to_apicid(int mps_cpu)
index 05a5385312294582a082592838f600c4b9ab7a32..7a17d9e58ad6586140e84a91a0a850b1b527e77a 100644 (file)
@@ -30,14 +30,10 @@ do {                                                                        \
                                                                        \
        __asm__ __volatile__(                                           \
                LOCK_PREFIX "   decl (%%eax)    \n"                     \
-                       "   js 2f               \n"                     \
+                       "   jns 1f              \n"                     \
+                       "   call "#fail_fn"     \n"                     \
                        "1:                     \n"                     \
                                                                        \
-               LOCK_SECTION_START("")                                  \
-                       "2: call "#fail_fn"     \n"                     \
-                       "   jmp 1b              \n"                     \
-               LOCK_SECTION_END                                        \
-                                                                       \
                :"=a" (dummy)                                           \
                : "a" (count)                                           \
                : "memory", "ecx", "edx");                              \
@@ -86,14 +82,10 @@ do {                                                                        \
                                                                        \
        __asm__ __volatile__(                                           \
                LOCK_PREFIX "   incl (%%eax)    \n"                     \
-                       "   jle 2f              \n"                     \
+                       "   jg  1f              \n"                     \
+                       "   call "#fail_fn"     \n"                     \
                        "1:                     \n"                     \
                                                                        \
-               LOCK_SECTION_START("")                                  \
-                       "2: call "#fail_fn"     \n"                     \
-                       "   jmp 1b              \n"                     \
-               LOCK_SECTION_END                                        \
-                                                                       \
                :"=a" (dummy)                                           \
                : "a" (count)                                           \
                : "memory", "ecx", "edx");                              \
index 67d99479999938450c2361656f7aeaa7911e3c04..303bcd4592bbe332337c10726dce6a0b3bd4c94a 100644 (file)
@@ -6,32 +6,29 @@
 
 #include <linux/pm.h>
 
-struct pt_regs;
-
-typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu);
-
 /**
- * set_nmi_callback
+ * do_nmi_callback
  *
- * Set a handler for an NMI. Only one handler may be
- * set. Return 1 if the NMI was handled.
+ * Check to see if a callback exists and execute it.  Return 1
+ * if the handler exists and was handled successfully.
  */
-void set_nmi_callback(nmi_callback_t callback);
-
-/**
- * unset_nmi_callback
- *
- * Remove the handler previously set.
- */
-void unset_nmi_callback(void);
-
-extern void setup_apic_nmi_watchdog (void);
-extern int reserve_lapic_nmi(void);
-extern void release_lapic_nmi(void);
+int do_nmi_callback(struct pt_regs *regs, int cpu);
+
+extern int nmi_watchdog_enabled;
+extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
+extern int avail_to_resrv_perfctr_nmi(unsigned int);
+extern int reserve_perfctr_nmi(unsigned int);
+extern void release_perfctr_nmi(unsigned int);
+extern int reserve_evntsel_nmi(unsigned int);
+extern void release_evntsel_nmi(unsigned int);
+
+extern void setup_apic_nmi_watchdog (void *);
+extern void stop_apic_nmi_watchdog (void *);
 extern void disable_timer_nmi_watchdog(void);
 extern void enable_timer_nmi_watchdog(void);
-extern void nmi_watchdog_tick (struct pt_regs * regs);
+extern int nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
 
+extern atomic_t nmi_active;
 extern unsigned int nmi_watchdog;
 #define NMI_DEFAULT     -1
 #define NMI_NONE       0
index 0dc051a8078b9b393a41236d4573f62f2bd9c15e..541b3e23433571d590f8e79291bb2c21fded9306 100644 (file)
@@ -411,8 +411,6 @@ extern pte_t *lookup_address(unsigned long address);
  static inline int set_kernel_exec(unsigned long vaddr, int enable) { return 0;}
 #endif
 
-extern void noexec_setup(const char *str);
-
 #if defined(CONFIG_HIGHPTE)
 #define pte_offset_map(dir, address) \
        ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
index 1910880fcd40d95aa67a4f3d242845acd90b59a9..a4a0e5207db58627c4ef02eb1a22eceb54c20a86 100644 (file)
@@ -27,6 +27,7 @@ struct pt_regs {
 #ifdef __KERNEL__
 
 #include <asm/vm86.h>
+#include <asm/segment.h>
 
 struct task_struct;
 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
@@ -40,18 +41,14 @@ extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int erro
  */
 static inline int user_mode(struct pt_regs *regs)
 {
-       return (regs->xcs & 3) != 0;
+       return (regs->xcs & SEGMENT_RPL_MASK) == USER_RPL;
 }
 static inline int user_mode_vm(struct pt_regs *regs)
 {
-       return ((regs->xcs & 3) | (regs->eflags & VM_MASK)) != 0;
+       return ((regs->xcs & SEGMENT_RPL_MASK) | (regs->eflags & VM_MASK)) >= USER_RPL;
 }
 #define instruction_pointer(regs) ((regs)->eip)
-#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
 extern unsigned long profile_pc(struct pt_regs *regs);
-#else
-#define profile_pc(regs) instruction_pointer(regs)
-#endif
 #endif /* __KERNEL__ */
 
 #endif
index 87c069ccba084dcd76045858ef50ca0878cc416c..c3e5db32fa48aca7a1c3d6edaf233a3b432c5922 100644 (file)
 #define RW_LOCK_BIAS            0x01000000
 #define RW_LOCK_BIAS_STR       "0x01000000"
 
-#define __build_read_lock_ptr(rw, helper)   \
-       asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t" \
-                       "jns 1f\n" \
-                       "call " helper "\n\t" \
-                       "1:\n" \
-                       ::"a" (rw) : "memory")
-
-#define __build_read_lock_const(rw, helper)   \
-       asm volatile(LOCK_PREFIX " subl $1,%0\n\t" \
-                       "jns 1f\n" \
-                       "pushl %%eax\n\t" \
-                       "leal %0,%%eax\n\t" \
-                       "call " helper "\n\t" \
-                       "popl %%eax\n\t" \
-                       "1:\n" \
-                       :"+m" (*(volatile int *)rw) : : "memory")
-
-#define __build_read_lock(rw, helper)  do { \
-                                               if (__builtin_constant_p(rw)) \
-                                                       __build_read_lock_const(rw, helper); \
-                                               else \
-                                                       __build_read_lock_ptr(rw, helper); \
-                                       } while (0)
-
-#define __build_write_lock_ptr(rw, helper) \
-       asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
-                       "jz 1f\n" \
-                       "call " helper "\n\t" \
-                       "1:\n" \
-                       ::"a" (rw) : "memory")
-
-#define __build_write_lock_const(rw, helper) \
-       asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
-                       "jz 1f\n" \
-                       "pushl %%eax\n\t" \
-                       "leal %0,%%eax\n\t" \
-                       "call " helper "\n\t" \
-                       "popl %%eax\n\t" \
-                       "1:\n" \
-                       :"+m" (*(volatile int *)rw) : : "memory")
-
-#define __build_write_lock(rw, helper) do { \
-                                               if (__builtin_constant_p(rw)) \
-                                                       __build_write_lock_const(rw, helper); \
-                                               else \
-                                                       __build_write_lock_ptr(rw, helper); \
-                                       } while (0)
+/* Code is in asm-i386/spinlock.h */
 
 #endif
index 43113f5608ebb930127ca4b1c16ac01cd991b2bb..bc598d6388e30ad44db8ae857402d7af4a2db3aa 100644 (file)
@@ -99,17 +99,9 @@ static inline void __down_read(struct rw_semaphore *sem)
        __asm__ __volatile__(
                "# beginning down_read\n\t"
 LOCK_PREFIX    "  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
-               "  js        2f\n\t" /* jump if we weren't granted the lock */
+               "  jns        1f\n"
+               "  call call_rwsem_down_read_failed\n"
                "1:\n\t"
-               LOCK_SECTION_START("")
-               "2:\n\t"
-               "  pushl     %%ecx\n\t"
-               "  pushl     %%edx\n\t"
-               "  call      rwsem_down_read_failed\n\t"
-               "  popl      %%edx\n\t"
-               "  popl      %%ecx\n\t"
-               "  jmp       1b\n"
-               LOCK_SECTION_END
                "# ending down_read\n\t"
                : "+m" (sem->count)
                : "a" (sem)
@@ -151,15 +143,9 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
                "# beginning down_write\n\t"
 LOCK_PREFIX    "  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
                "  testl     %%edx,%%edx\n\t" /* was the count 0 before? */
-               "  jnz       2f\n\t" /* jump if we weren't granted the lock */
-               "1:\n\t"
-               LOCK_SECTION_START("")
-               "2:\n\t"
-               "  pushl     %%ecx\n\t"
-               "  call      rwsem_down_write_failed\n\t"
-               "  popl      %%ecx\n\t"
-               "  jmp       1b\n"
-               LOCK_SECTION_END
+               "  jz        1f\n"
+               "  call call_rwsem_down_write_failed\n"
+               "1:\n"
                "# ending down_write"
                : "+m" (sem->count), "=d" (tmp)
                : "a" (sem), "1" (tmp)
@@ -193,17 +179,9 @@ static inline void __up_read(struct rw_semaphore *sem)
        __asm__ __volatile__(
                "# beginning __up_read\n\t"
 LOCK_PREFIX    "  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
-               "  js        2f\n\t" /* jump if the lock is being waited upon */
-               "1:\n\t"
-               LOCK_SECTION_START("")
-               "2:\n\t"
-               "  decw      %%dx\n\t" /* do nothing if still outstanding active readers */
-               "  jnz       1b\n\t"
-               "  pushl     %%ecx\n\t"
-               "  call      rwsem_wake\n\t"
-               "  popl      %%ecx\n\t"
-               "  jmp       1b\n"
-               LOCK_SECTION_END
+               "  jns        1f\n\t"
+               "  call call_rwsem_wake\n"
+               "1:\n"
                "# ending __up_read\n"
                : "+m" (sem->count), "=d" (tmp)
                : "a" (sem), "1" (tmp)
@@ -219,17 +197,9 @@ static inline void __up_write(struct rw_semaphore *sem)
                "# beginning __up_write\n\t"
                "  movl      %2,%%edx\n\t"
 LOCK_PREFIX    "  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
-               "  jnz       2f\n\t" /* jump if the lock is being waited upon */
+               "  jz       1f\n"
+               "  call call_rwsem_wake\n"
                "1:\n\t"
-               LOCK_SECTION_START("")
-               "2:\n\t"
-               "  decw      %%dx\n\t" /* did the active count reduce to 0? */
-               "  jnz       1b\n\t" /* jump back if not */
-               "  pushl     %%ecx\n\t"
-               "  call      rwsem_wake\n\t"
-               "  popl      %%ecx\n\t"
-               "  jmp       1b\n"
-               LOCK_SECTION_END
                "# ending __up_write\n"
                : "+m" (sem->count)
                : "a" (sem), "i" (-RWSEM_ACTIVE_WRITE_BIAS)
@@ -244,17 +214,9 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
        __asm__ __volatile__(
                "# beginning __downgrade_write\n\t"
 LOCK_PREFIX    "  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
-               "  js        2f\n\t" /* jump if the lock is being waited upon */
+               "  jns       1f\n\t"
+               "  call call_rwsem_downgrade_wake\n"
                "1:\n\t"
-               LOCK_SECTION_START("")
-               "2:\n\t"
-               "  pushl     %%ecx\n\t"
-               "  pushl     %%edx\n\t"
-               "  call      rwsem_downgrade_wake\n\t"
-               "  popl      %%edx\n\t"
-               "  popl      %%ecx\n\t"
-               "  jmp       1b\n"
-               LOCK_SECTION_END
                "# ending __downgrade_write\n"
                : "+m" (sem->count)
                : "a" (sem), "i" (-RWSEM_WAITING_BIAS)
index faf995307b9e66428f06e9afd514217760c4f61a..b7ab59685ba7f1784769f7247ba839c048e5f72a 100644 (file)
 
 #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
  */
 #define IDT_ENTRIES 256
 
+/* Bottom two bits of selector give the ring privilege level */
+#define SEGMENT_RPL_MASK       0x3
+/* Bit 2 is table indicator (LDT/GDT) */
+#define SEGMENT_TI_MASK                0x4
+
+/* User mode is privilege level 3 */
+#define USER_RPL               0x3
+/* LDT segment has TI set, GDT has it cleared */
+#define SEGMENT_LDT            0x4
+#define SEGMENT_GDT            0x0
+
+#define get_kernel_rpl()  0
 #endif
index d51e800acf29527dc84907784f848b6676ecae02..4e34a468c3835cc323eea52518f5c916cea79691 100644 (file)
@@ -100,13 +100,10 @@ static inline void down(struct semaphore * sem)
        __asm__ __volatile__(
                "# atomic down operation\n\t"
                LOCK_PREFIX "decl %0\n\t"     /* --sem->count */
-               "js 2f\n"
-               "1:\n"
-               LOCK_SECTION_START("")
-               "2:\tlea %0,%%eax\n\t"
-               "call __down_failed\n\t"
-               "jmp 1b\n"
-               LOCK_SECTION_END
+               "jns 2f\n"
+               "\tlea %0,%%eax\n\t"
+               "call __down_failed\n"
+               "2:"
                :"+m" (sem->count)
                :
                :"memory","ax");
@@ -123,16 +120,13 @@ static inline int down_interruptible(struct semaphore * sem)
        might_sleep();
        __asm__ __volatile__(
                "# atomic interruptible down operation\n\t"
+               "xorl %0,%0\n\t"
                LOCK_PREFIX "decl %1\n\t"     /* --sem->count */
-               "js 2f\n\t"
-               "xorl %0,%0\n"
-               "1:\n"
-               LOCK_SECTION_START("")
-               "2:\tlea %1,%%eax\n\t"
-               "call __down_failed_interruptible\n\t"
-               "jmp 1b\n"
-               LOCK_SECTION_END
-               :"=a" (result), "+m" (sem->count)
+               "jns 2f\n\t"
+               "lea %1,%%eax\n\t"
+               "call __down_failed_interruptible\n"
+               "2:"
+               :"=&a" (result), "+m" (sem->count)
                :
                :"memory");
        return result;
@@ -148,16 +142,13 @@ static inline int down_trylock(struct semaphore * sem)
 
        __asm__ __volatile__(
                "# atomic interruptible down operation\n\t"
+               "xorl %0,%0\n\t"
                LOCK_PREFIX "decl %1\n\t"     /* --sem->count */
-               "js 2f\n\t"
-               "xorl %0,%0\n"
-               "1:\n"
-               LOCK_SECTION_START("")
-               "2:\tlea %1,%%eax\n\t"
+               "jns 2f\n\t"
+               "lea %1,%%eax\n\t"
                "call __down_failed_trylock\n\t"
-               "jmp 1b\n"
-               LOCK_SECTION_END
-               :"=a" (result), "+m" (sem->count)
+               "2:\n"
+               :"=&a" (result), "+m" (sem->count)
                :
                :"memory");
        return result;
@@ -166,22 +157,16 @@ static inline int down_trylock(struct semaphore * sem)
 /*
  * Note! This is subtle. We jump to wake people up only if
  * the semaphore was negative (== somebody was waiting on it).
- * The default case (no contention) will result in NO
- * jumps for both down() and up().
  */
 static inline void up(struct semaphore * sem)
 {
        __asm__ __volatile__(
                "# atomic up operation\n\t"
                LOCK_PREFIX "incl %0\n\t"     /* ++sem->count */
-               "jle 2f\n"
-               "1:\n"
-               LOCK_SECTION_START("")
-               "2:\tlea %0,%%eax\n\t"
-               "call __up_wakeup\n\t"
-               "jmp 1b\n"
-               LOCK_SECTION_END
-               ".subsection 0\n"
+               "jg 1f\n\t"
+               "lea %0,%%eax\n\t"
+               "call __up_wakeup\n"
+               "1:"
                :"+m" (sem->count)
                :
                :"memory","ax");
index 142d10e34adeac2c4960e90018575c2094c28a62..32ac8c91d5c5ccb2e8856ee2a6943d59609d090e 100644 (file)
@@ -80,17 +80,12 @@ static inline int hard_smp_processor_id(void)
        return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID));
 }
 #endif
-
-static __inline int logical_smp_processor_id(void)
-{
-       /* we don't want to mark this access volatile - bad code generation */
-       return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
-}
-
 #endif
 
 extern int __cpu_disable(void);
 extern void __cpu_die(unsigned int cpu);
+extern unsigned int num_processors;
+
 #endif /* !__ASSEMBLY__ */
 
 #else /* CONFIG_SMP */
@@ -100,4 +95,15 @@ extern void __cpu_die(unsigned int cpu);
 #define NO_PROC_ID             0xFF            /* No processor magic marker */
 
 #endif
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_X86_LOCAL_APIC
+static __inline int logical_smp_processor_id(void)
+{
+       /* we don't want to mark this access volatile - bad code generation */
+       return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
+}
+#endif
+#endif
+
 #endif
index d1020363c41ab744cebcb2ae4896849fbe10c6b2..b0b3043f05e154742738f5ff03b7c409d265f2f4 100644 (file)
@@ -4,8 +4,12 @@
 #include <asm/atomic.h>
 #include <asm/rwlock.h>
 #include <asm/page.h>
+#include <asm/processor.h>
 #include <linux/compiler.h>
 
+#define CLI_STRING     "cli"
+#define STI_STRING     "sti"
+
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  *
  * (the type definitions are in asm/spinlock_types.h)
  */
 
-#define __raw_spin_is_locked(x) \
-               (*(volatile signed char *)(&(x)->slock) <= 0)
-
-#define __raw_spin_lock_string \
-       "\n1:\t" \
-       LOCK_PREFIX " ; decb %0\n\t" \
-       "jns 3f\n" \
-       "2:\t" \
-       "rep;nop\n\t" \
-       "cmpb $0,%0\n\t" \
-       "jle 2b\n\t" \
-       "jmp 1b\n" \
-       "3:\n\t"
-
-/*
- * NOTE: there's an irqs-on section here, which normally would have to be
- * irq-traced, but on CONFIG_TRACE_IRQFLAGS we never use
- * __raw_spin_lock_string_flags().
- */
-#define __raw_spin_lock_string_flags \
-       "\n1:\t" \
-       LOCK_PREFIX " ; decb %0\n\t" \
-       "jns 5f\n" \
-       "2:\t" \
-       "testl $0x200, %1\n\t" \
-       "jz 4f\n\t" \
-       "sti\n" \
-       "3:\t" \
-       "rep;nop\n\t" \
-       "cmpb $0, %0\n\t" \
-       "jle 3b\n\t" \
-       "cli\n\t" \
-       "jmp 1b\n" \
-       "4:\t" \
-       "rep;nop\n\t" \
-       "cmpb $0, %0\n\t" \
-       "jg 1b\n\t" \
-       "jmp 4b\n" \
-       "5:\n\t"
+static inline int __raw_spin_is_locked(raw_spinlock_t *x)
+{
+       return *(volatile signed char *)(&(x)->slock) <= 0;
+}
 
 static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
-       asm(__raw_spin_lock_string : "+m" (lock->slock) : : "memory");
+       asm volatile("\n1:\t"
+                    LOCK_PREFIX " ; decb %0\n\t"
+                    "jns 3f\n"
+                    "2:\t"
+                    "rep;nop\n\t"
+                    "cmpb $0,%0\n\t"
+                    "jle 2b\n\t"
+                    "jmp 1b\n"
+                    "3:\n\t"
+                    : "+m" (lock->slock) : : "memory");
 }
 
 /*
  * It is easier for the lock validator if interrupts are not re-enabled
  * in the middle of a lock-acquire. This is a performance feature anyway
  * so we turn it off:
+ *
+ * NOTE: there's an irqs-on section here, which normally would have to be
+ * irq-traced, but on CONFIG_TRACE_IRQFLAGS we never use this variant.
  */
 #ifndef CONFIG_PROVE_LOCKING
 static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
 {
-       asm(__raw_spin_lock_string_flags : "+m" (lock->slock) : "r" (flags) : "memory");
+       asm volatile(
+               "\n1:\t"
+               LOCK_PREFIX " ; decb %0\n\t"
+               "jns 5f\n"
+               "2:\t"
+               "testl $0x200, %1\n\t"
+               "jz 4f\n\t"
+               STI_STRING "\n"
+               "3:\t"
+               "rep;nop\n\t"
+               "cmpb $0, %0\n\t"
+               "jle 3b\n\t"
+               CLI_STRING "\n\t"
+               "jmp 1b\n"
+               "4:\t"
+               "rep;nop\n\t"
+               "cmpb $0, %0\n\t"
+               "jg 1b\n\t"
+               "jmp 4b\n"
+               "5:\n\t"
+               : "+m" (lock->slock) : "r" (flags) : "memory");
 }
 #endif
 
 static inline int __raw_spin_trylock(raw_spinlock_t *lock)
 {
        char oldval;
-       __asm__ __volatile__(
+       asm volatile(
                "xchgb %b0,%1"
                :"=q" (oldval), "+m" (lock->slock)
                :"0" (0) : "memory");
@@ -93,38 +94,29 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock)
 
 #if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE)
 
-#define __raw_spin_unlock_string \
-       "movb $1,%0" \
-               :"+m" (lock->slock) : : "memory"
-
-
 static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
-       __asm__ __volatile__(
-               __raw_spin_unlock_string
-       );
+       asm volatile("movb $1,%0" : "+m" (lock->slock) :: "memory");
 }
 
 #else
 
-#define __raw_spin_unlock_string \
-       "xchgb %b0, %1" \
-               :"=q" (oldval), "+m" (lock->slock) \
-               :"0" (oldval) : "memory"
-
 static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
        char oldval = 1;
 
-       __asm__ __volatile__(
-               __raw_spin_unlock_string
-       );
+       asm volatile("xchgb %b0, %1"
+                    : "=q" (oldval), "+m" (lock->slock)
+                    : "0" (oldval) : "memory");
 }
 
 #endif
 
-#define __raw_spin_unlock_wait(lock) \
-       do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
+static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
+{
+       while (__raw_spin_is_locked(lock))
+               cpu_relax();
+}
 
 /*
  * Read-write spinlocks, allowing multiple readers
@@ -151,22 +143,36 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock)
  * read_can_lock - would read_trylock() succeed?
  * @lock: the rwlock in question.
  */
-#define __raw_read_can_lock(x)         ((int)(x)->lock > 0)
+static inline int __raw_read_can_lock(raw_rwlock_t *x)
+{
+       return (int)(x)->lock > 0;
+}
 
 /**
  * write_can_lock - would write_trylock() succeed?
  * @lock: the rwlock in question.
  */
-#define __raw_write_can_lock(x)                ((x)->lock == RW_LOCK_BIAS)
+static inline int __raw_write_can_lock(raw_rwlock_t *x)
+{
+       return (x)->lock == RW_LOCK_BIAS;
+}
 
 static inline void __raw_read_lock(raw_rwlock_t *rw)
 {
-       __build_read_lock(rw, "__read_lock_failed");
+       asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t"
+                    "jns 1f\n"
+                    "call __read_lock_failed\n\t"
+                    "1:\n"
+                    ::"a" (rw) : "memory");
 }
 
 static inline void __raw_write_lock(raw_rwlock_t *rw)
 {
-       __build_write_lock(rw, "__write_lock_failed");
+       asm volatile(LOCK_PREFIX " subl $" RW_LOCK_BIAS_STR ",(%0)\n\t"
+                    "jz 1f\n"
+                    "call __write_lock_failed\n\t"
+                    "1:\n"
+                    ::"a" (rw) : "memory");
 }
 
 static inline int __raw_read_trylock(raw_rwlock_t *lock)
diff --git a/include/asm-i386/stacktrace.h b/include/asm-i386/stacktrace.h
new file mode 100644 (file)
index 0000000..7d1f6a5
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-x86_64/stacktrace.h>
diff --git a/include/asm-i386/therm_throt.h b/include/asm-i386/therm_throt.h
new file mode 100644 (file)
index 0000000..399bf60
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __ASM_I386_THERM_THROT_H__
+#define __ASM_I386_THERM_THROT_H__ 1
+
+#include <asm/atomic.h>
+
+extern atomic_t therm_throt_en;
+int therm_throt_process(int curr);
+
+#endif /* __ASM_I386_THERM_THROT_H__ */
index d57ca5c540b69cd74821e9ca7cec039a9e3b805a..360648b0f2b3888235e95f8b7420879934a9e0bc 100644 (file)
@@ -36,8 +36,6 @@
                        : "memory");                                    \
        } while (0)
 
-extern unsigned long pgkern_mask;
-
 # define __flush_tlb_all()                                             \
        do {                                                            \
                if (cpu_has_pge)                                        \
@@ -49,7 +47,7 @@ extern unsigned long pgkern_mask;
 #define cpu_has_invlpg (boot_cpu_data.x86 > 3)
 
 #define __flush_tlb_single(addr) \
-       __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
+       __asm__ __volatile__("invlpg (%0)" ::"r" (addr) : "memory")
 
 #ifdef CONFIG_X86_INVLPG
 # define __flush_tlb_one(addr) __flush_tlb_single(addr)
index 97b828ce31e0b8687d7bd04a6d5cbf278d6fc0dd..c13933185c1cc20f1a0b0cfbc01d67f92bee26dc 100644 (file)
@@ -6,7 +6,6 @@
 #ifndef _ASM_i386_TSC_H
 #define _ASM_i386_TSC_H
 
-#include <linux/config.h>
 #include <asm/processor.h>
 
 /*
index fc1c8ddae149830a0442e8e9cb7609068c0792cb..bd9987087adc6adb90d95daabf67c4eba7be8392 100644 (file)
 #define __NR_tee               315
 #define __NR_vmsplice          316
 #define __NR_move_pages                317
+#define __NR_getcpu            318
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 318
+#define NR_syscalls 319
+#include <linux/err.h>
 
 /*
- * user-visible error numbers are in the range -1 - -128: see
+ * user-visible error numbers are in the range -1 - -MAX_ERRNO: see
  * <asm-i386/errno.h>
  */
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-(128 + 1))) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
                errno = -(res); \
                res = -1; \
        } \
index 4c1a0b968569ef64844d1ad5d159ce7b44141249..5031d693b89d35fb3f7cfce8db78a79bb1db5503 100644 (file)
@@ -18,6 +18,7 @@ struct unwind_frame_info
 {
        struct pt_regs regs;
        struct task_struct *task;
+       unsigned call_frame:1;
 };
 
 #define UNW_PC(frame)        (frame)->regs.eip
@@ -28,6 +29,8 @@ struct unwind_frame_info
 #define FRAME_LINK_OFFSET    0
 #define STACK_BOTTOM(tsk)    STACK_LIMIT((tsk)->thread.esp0)
 #define STACK_TOP(tsk)       ((tsk)->thread.esp0)
+#else
+#define UNW_FP(frame) ((void)(frame), 0)
 #endif
 #define STACK_LIMIT(ptr)     (((ptr) - 1) & ~(THREAD_SIZE - 1))
 
@@ -42,6 +45,10 @@ struct unwind_frame_info
        PTREGS_INFO(edi), \
        PTREGS_INFO(eip)
 
+#define UNW_DEFAULT_RA(raItem, dataAlign) \
+       ((raItem).where == Memory && \
+        !((raItem).value * (dataAlign) + 4))
+
 static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
                                             /*const*/ struct pt_regs *regs)
 {
@@ -88,6 +95,7 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
 
 #define UNW_PC(frame) ((void)(frame), 0)
 #define UNW_SP(frame) ((void)(frame), 0)
+#define UNW_FP(frame) ((void)(frame), 0)
 
 static inline int arch_unw_user_mode(const void *info)
 {
diff --git a/include/asm-ia64/esi.h b/include/asm-ia64/esi.h
new file mode 100644 (file)
index 0000000..84aac0e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * ESI service calls.
+ *
+ * Copyright (c) Copyright 2005-2006 Hewlett-Packard Development Company, L.P.
+ *     Alex Williamson <alex.williamson@hp.com>
+ */
+#ifndef esi_h
+#define esi_h
+
+#include <linux/efi.h>
+
+#define ESI_QUERY                      0x00000001
+#define ESI_OPEN_HANDLE                        0x02000000
+#define ESI_CLOSE_HANDLE               0x02000001
+
+enum esi_proc_type {
+       ESI_PROC_SERIALIZED,    /* calls need to be serialized */
+       ESI_PROC_MP_SAFE,       /* MP-safe, but not reentrant */
+       ESI_PROC_REENTRANT      /* MP-safe and reentrant */
+};
+
+extern int ia64_esi_init (void);
+extern struct ia64_sal_retval esi_call_phys (void *, u64 *);
+extern int ia64_esi_call(efi_guid_t, struct ia64_sal_retval *,
+                        enum esi_proc_type,
+                        u64, u64, u64, u64, u64, u64, u64, u64);
+extern int ia64_esi_call_phys(efi_guid_t, struct ia64_sal_retval *, u64, u64,
+                              u64, u64, u64, u64, u64, u64);
+
+#endif /* esi_h */
index 6a332a9f099c2eafbf78ee5f79056a349d41a775..07d77f3a8cbe278bbad15d99e80442b86cbd7d83 100644 (file)
@@ -1,6 +1,124 @@
 #ifndef _ASM_FUTEX_H
 #define _ASM_FUTEX_H
 
-#include <asm-generic/futex.h>
+#include <linux/futex.h>
+#include <asm/errno.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
 
-#endif
+#define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \
+do {                                                                   \
+       register unsigned long r8 __asm ("r8") = 0;                     \
+       __asm__ __volatile__(                                           \
+               "       mf;;                                    \n"     \
+               "[1:] " insn ";;                                \n"     \
+               "       .xdata4 \"__ex_table\", 1b-., 2f-.      \n"     \
+               "[2:]"                                                  \
+               : "+r" (r8), "=r" (oldval)                              \
+               : "r" (uaddr), "r" (oparg)                              \
+               : "memory");                                            \
+       ret = r8;                                                       \
+} while (0)
+
+#define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \
+do {                                                                   \
+       register unsigned long r8 __asm ("r8") = 0;                     \
+       int val, newval;                                                \
+       do {                                                            \
+               __asm__ __volatile__(                                   \
+                       "       mf;;                              \n"   \
+                       "[1:]   ld4 %3=[%4];;                     \n"   \
+                       "       mov %2=%3                         \n"   \
+                               insn    ";;                       \n"   \
+                       "       mov ar.ccv=%2;;                   \n"   \
+                       "[2:]   cmpxchg4.acq %1=[%4],%3,ar.ccv;;  \n"   \
+                       "       .xdata4 \"__ex_table\", 1b-., 3f-.\n"   \
+                       "       .xdata4 \"__ex_table\", 2b-., 3f-.\n"   \
+                       "[3:]"                                          \
+                       : "+r" (r8), "=r" (val), "=&r" (oldval),        \
+                          "=&r" (newval)                               \
+                       : "r" (uaddr), "r" (oparg)                      \
+                       : "memory");                                    \
+               if (unlikely (r8))                                      \
+                       break;                                          \
+       } while (unlikely (val != oldval));                             \
+       ret = r8;                                                       \
+} while (0)
+
+static inline int
+futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+       int op = (encoded_op >> 28) & 7;
+       int cmp = (encoded_op >> 24) & 15;
+       int oparg = (encoded_op << 8) >> 20;
+       int cmparg = (encoded_op << 20) >> 20;
+       int oldval = 0, ret;
+       if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+               oparg = 1 << oparg;
+
+       if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       inc_preempt_count();
+
+       switch (op) {
+       case FUTEX_OP_SET:
+               __futex_atomic_op1("xchg4 %1=[%2],%3", ret, oldval, uaddr,
+                                  oparg);
+               break;
+       case FUTEX_OP_ADD:
+               __futex_atomic_op2("add %3=%3,%5", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_OR:
+               __futex_atomic_op2("or %3=%3,%5", ret, oldval, uaddr, oparg);
+               break;
+       case FUTEX_OP_ANDN:
+               __futex_atomic_op2("and %3=%3,%5", ret, oldval, uaddr,
+                                  ~oparg);
+               break;
+       case FUTEX_OP_XOR:
+               __futex_atomic_op2("xor %3=%3,%5", ret, oldval, uaddr, oparg);
+               break;
+       default:
+               ret = -ENOSYS;
+       }
+
+       dec_preempt_count();
+
+       if (!ret) {
+               switch (cmp) {
+               case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+               case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+               case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+               case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+               case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+               case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+               default: ret = -ENOSYS;
+               }
+       }
+       return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+       if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+               return -EFAULT;
+
+       {
+               register unsigned long r8 __asm ("r8");
+               __asm__ __volatile__(
+                       "       mf;;                                    \n"
+                       "       mov ar.ccv=%3;;                         \n"
+                       "[1:]   cmpxchg4.acq %0=[%1],%2,ar.ccv          \n"
+                       "       .xdata4 \"__ex_table\", 1b-., 2f-.      \n"
+                       "[2:]"
+                       : "=r" (r8)
+                       : "r" (uaddr), "r" (newval),
+                         "rO" ((long) (unsigned) oldval)
+                       : "memory");
+               return r8;
+       }
+}
+
+#endif /* _ASM_FUTEX_H */
index 9389049101157360555125760c2c4c268d9426ff..1b45b71c79b98bfe0c0f9bc51855920e3b0b35a0 100644 (file)
@@ -29,7 +29,8 @@
 #include <linux/percpu.h>
 #include <asm/break.h>
 
-#define MAX_INSN_SIZE   16
+#define __ARCH_WANT_KPROBES_INSN_SLOT
+#define MAX_INSN_SIZE   1
 #define BREAK_INST     (long)(__IA64_BREAK_KPROBE << 6)
 
 typedef union cmp_inst {
@@ -94,7 +95,7 @@ struct kprobe_ctlblk {
 #define IP_RELATIVE_PREDICT_OPCODE     (7)
 #define LONG_BRANCH_OPCODE             (0xC)
 #define LONG_CALL_OPCODE               (0xD)
-#define arch_remove_kprobe(p)          do {} while (0)
+#define flush_insn_slot(p)             do { } while (0)
 
 typedef struct kprobe_opcode {
        bundle_t bundle;
@@ -108,7 +109,7 @@ struct fnptr {
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
        /* copy of the instruction to be emulated */
-       kprobe_opcode_t insn;
+       kprobe_opcode_t *insn;
  #define INST_FLAG_FIX_RELATIVE_IP_ADDR                1
  #define INST_FLAG_FIX_BRANCH_REG              2
  #define INST_FLAG_BREAK_INST                  4
@@ -125,6 +126,6 @@ static inline void jprobe_return(void)
 }
 extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
-extern void flush_insn_slot(struct kprobe *p);
+extern void arch_remove_kprobe(struct kprobe *p);
 
 #endif                         /* _ASM_KPROBES_H */
index 27c9203d8ce3173bff55753e1882a651faf11bc6..76203f9a8718d6706216a961684205f6beffbdaa 100644 (file)
        movl    temp2 = start_addr;                             \
        ;;                                                      \
        mov     cr.iip = temp2;                                 \
+       movl    gp = __gp                                       \
        ;;                                                      \
        DATA_PA_TO_VA(sp, temp1);                               \
-       DATA_PA_TO_VA(gp, temp2);                               \
        srlz.i;                                                 \
        ;;                                                      \
        nop     1;                                              \
index 6a33a07b3f1dfc608a5995a871896dac5c00b4ef..c3b1f862e6e75dfda6b1f677d8f358df0cc4fbad 100644 (file)
@@ -55,6 +55,7 @@ extern void efi_memmap_init(unsigned long *, unsigned long *);
   extern unsigned long vmalloc_end;
   extern struct page *vmem_map;
   extern int find_largest_hole (u64 start, u64 end, void *arg);
+  extern int register_active_ranges (u64 start, u64 end, void *arg);
   extern int create_mem_map_page_table (u64 start, u64 end, void *arg);
   extern int vmemmap_find_next_valid_pfn(int, int);
 #else
index 85c82bd819f253009338af96ad04e939b011b720..d2da61e4c49bb690021e332f38bace45d3a1e4b7 100644 (file)
@@ -28,7 +28,8 @@ struct mod_arch_specific {
 #define Elf_Ehdr       Elf64_Ehdr
 
 #define MODULE_PROC_FAMILY     "ia64"
-#define MODULE_ARCH_VERMAGIC   MODULE_PROC_FAMILY
+#define MODULE_ARCH_VERMAGIC   MODULE_PROC_FAMILY \
+       "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
 
 #define ARCH_SHF_SMALL SHF_IA_64_SHORT
 
index e0a1d173e42df07fd74ebee65ffde116b9e76ec9..7d5e2ccc37a079fb4fe2ffbd16d69c919c6610a5 100644 (file)
@@ -69,6 +69,8 @@ extern void unmap_cpu_from_node(int cpu, int nid);
 
 
 #else /* !CONFIG_NUMA */
+#define map_cpu_to_node(cpu, nid)      do{}while(0)
+#define unmap_cpu_from_node(cpu, nid)  do{}while(0)
 
 #define paddr_to_nid(addr)     0
 
index 20a8d618c8454776b441245317c21d7e19444a87..2c8fd92d0ece088e36b15548588947a59fd5cea7 100644 (file)
@@ -78,6 +78,7 @@
 #define PAL_VM_TR_READ         261     /* read contents of translation register */
 #define PAL_GET_PSTATE         262     /* get the current P-state */
 #define PAL_SET_PSTATE         263     /* set the P-state */
+#define PAL_BRAND_INFO         274     /* Processor branding information */
 
 #ifndef __ASSEMBLY__
 
@@ -963,7 +964,8 @@ static inline s64
 ia64_pal_cache_read (pal_cache_line_id_u_t line_id, u64 physical_addr)
 {
        struct ia64_pal_retval iprv;
-       PAL_CALL(iprv, PAL_CACHE_READ, line_id.pclid_data, physical_addr, 0);
+       PAL_CALL_PHYS_STK(iprv, PAL_CACHE_READ, line_id.pclid_data,
+                               physical_addr, 0);
        return iprv.status;
 }
 
@@ -985,7 +987,8 @@ static inline s64
 ia64_pal_cache_write (pal_cache_line_id_u_t line_id, u64 physical_addr, u64 data)
 {
        struct ia64_pal_retval iprv;
-       PAL_CALL(iprv, PAL_CACHE_WRITE, line_id.pclid_data, physical_addr, data);
+       PAL_CALL_PHYS_STK(iprv, PAL_CACHE_WRITE, line_id.pclid_data,
+                               physical_addr, data);
        return iprv.status;
 }
 
@@ -1133,6 +1136,15 @@ ia64_pal_set_pstate (u64 pstate_index)
        return iprv.status;
 }
 
+/* Processor branding information*/
+static inline s64
+ia64_pal_get_brand_info (char *brand_info)
+{
+       struct ia64_pal_retval iprv;
+       PAL_CALL_STK(iprv, PAL_BRAND_INFO, 0, (u64)brand_info, 0);
+       return iprv.status;
+}
+
 /* Cause the processor to enter LIGHT HALT state, where prefetching and execution are
  * suspended, but cache and TLB coherency is maintained.
  */
index 265f4824db0e2e6ea04abc225f81758547a8de62..5830d36fd8e6a407697001a1f5c0aeef9c4747f6 100644 (file)
 #include <asm/ustack.h>
 
 #define IA64_NUM_DBG_REGS      8
-/*
- * Limits for PMC and PMD are set to less than maximum architected values
- * but should be sufficient for a while
- */
-#define IA64_NUM_PMC_REGS      64
-#define IA64_NUM_PMD_REGS      64
 
 #define DEFAULT_MAP_BASE       __IA64_UL_CONST(0x2000000000000000)
 #define DEFAULT_TASK_SIZE      __IA64_UL_CONST(0xa000000000000000)
@@ -163,6 +157,7 @@ struct cpuinfo_ia64 {
        __u8 family;
        __u8 archrev;
        char vendor[16];
+       char *model_name;
 
 #ifdef CONFIG_NUMA
        struct ia64_node_data *node_data;
@@ -262,13 +257,9 @@ struct thread_struct {
 # define INIT_THREAD_IA32
 #endif /* CONFIG_IA32_SUPPORT */
 #ifdef CONFIG_PERFMON
-       __u64 pmcs[IA64_NUM_PMC_REGS];
-       __u64 pmds[IA64_NUM_PMD_REGS];
        void *pfm_context;                   /* pointer to detailed PMU context */
        unsigned long pfm_needs_checking;    /* when >0, pending perfmon work on kernel exit */
-# define INIT_THREAD_PM                .pmcs =                 {0UL, },  \
-                               .pmds =                 {0UL, },  \
-                               .pfm_context =          NULL,     \
+# define INIT_THREAD_PM                .pfm_context =          NULL,     \
                                .pfm_needs_checking =   0UL,
 #else
 # define INIT_THREAD_PM
index 74bde1c2bb1a93b48c2c4ac78df57dc8965913b5..60fd4ae014f6fbe8a3fe19b8e9171a7e277f609e 100644 (file)
@@ -126,6 +126,7 @@ extern void smp_send_reschedule (int cpu);
 extern void lock_ipi_calllock(void);
 extern void unlock_ipi_calllock(void);
 extern void identify_siblings (struct cpuinfo_ia64 *);
+extern int is_multithreading_enabled(void);
 
 #else
 
index f581662c5ab8a8ee7ef75e592ad48e626b43038f..bb0eb727dcd086fb15d43135ca7e0e20ebb4cdf8 100644 (file)
 /* 1294, 1295 reserved for pselect/ppoll */
 #define __NR_unshare                   1296
 #define __NR_splice                    1297
-/* 1298, 1299 reserved for set_robust_list/get_robust_list */
+#define __NR_set_robust_list           1298
+#define __NR_get_robust_list           1299
 #define __NR_sync_file_range           1300
 #define __NR_tee                       1301
 #define __NR_vmsplice                  1302
index f94c1a673569109cbe336c2849b7f228183bc988..f9f90727a4a1f9c88485150e380db6113d461218 100644 (file)
@@ -298,7 +298,14 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
        );
 }
 
-#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
+static inline int __raw_read_trylock(raw_rwlock_t *lock)
+{
+       atomic_t *count = (atomic_t*)lock;
+       if (atomic_dec_return(count) >= 0)
+               return 1;
+       atomic_inc(count);
+       return 0;
+}
 
 static inline int __raw_write_trylock(raw_rwlock_t *lock)
 {
index 9e618afec6ed7bd6480962dfa85abb2931c61e7a..4ce0619f6989024855782484766eb0adfa88cc78 100644 (file)
@@ -328,15 +328,15 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
 #define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
 #define smp_read_barrier_depends()     read_barrier_depends()
+#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
 #else
 #define smp_mb()       barrier()
 #define smp_rmb()      barrier()
 #define smp_wmb()      barrier()
 #define smp_read_barrier_depends()     do { } while (0)
+#define set_mb(var, value) do { var = value; barrier(); } while (0)
 #endif
 
-#define set_mb(var, value) do { xchg(&var, value); } while (0)
-
 #define arch_align_stack(x) (x)
 
 #endif  /* _ASM_M32R_SYSTEM_H */
index 89f376e6229f7ddb2cf332a613177e9f09f1b19a..5c6a9ac6cf1aea11eefcca4969dae98057e6c724 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls 285
+#include <linux/err.h>
 
-/* user-visible error numbers are in the range -1 - -124: see
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see
  * <asm-m32r/errno.h>
  */
 
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-(124 + 1))) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
        /* Avoid using "res" which is declared to be in register r0; \
           errno might expand to a function call and clobber it.  */ \
                int __err = -(res); \
index 7c0b6296b45c6b8c14cd545deb9a565b5db78f0d..751632b904dbca90a4e8a1967ff24a28815d9532 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls            282
+#include <linux/err.h>
 
-/* user-visible error numbers are in the range -1 - -124: see
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see
    <asm-m68k/errno.h> */
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
        /* avoid using res which is declared to be in register d0; \
           errno might expand to a function call and clobber it.  */ \
                int __err = -(res); \
index 1b2abdf281e1800b62f66bdda3b7ff9a9057bfb9..21fdc37c5c2c60c8c4e69d0a6829efa297042dc9 100644 (file)
 #ifdef __KERNEL__
 
 #define NR_syscalls            282
+#include <linux/err.h>
 
-/* user-visible error numbers are in the range -1 - -122: see
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO: see
    <asm-m68k/errno.h> */
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
        /* avoid using res which is declared to be in register d0; \
           errno might expand to a function call and clobber it.  */ \
                int __err = -(res); \
index c68e1680da0173d5754d1a1df4944120a5239e58..7897f05e316520ed5279e479eef15a4278a6afa9 100644 (file)
@@ -1 +1,3 @@
 include include/asm-generic/Kbuild.asm
+
+header-y += cachectl.h sgidefs.h sysmips.h
index 3b745e76f429bd0bea3e2615d33136bdc82ba9e1..78c35ec463624d2c4d337f9dbd2d2c2a25701301 100644 (file)
  * Valid machtype for group GALILEO
  */
 #define MACH_GROUP_GALILEO     11      /* Galileo Eval Boards          */
-#define  MACH_EV96100          0       /* EV96100 */
-#define  MACH_EV64120A         1       /* EV64120A */
+#define  MACH_EV64120A         0       /* EV64120A */
 
 /*
  * Valid machtype for group MOMENCO
index 47bc8f6c20d2e2795211335e37cbb4e01489e0c2..36416fdfcf6893030e4f0325e8407023857babc0 100644 (file)
@@ -21,7 +21,6 @@
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *  - flush_icache_range(start, end) flush a range of instructions
  *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
- *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
  *
  * MIPS specific flush operations:
  *
@@ -39,7 +38,7 @@ extern void __flush_dcache_page(struct page *page);
 
 static inline void flush_dcache_page(struct page *page)
 {
-       if (cpu_has_dc_aliases)
+       if (cpu_has_dc_aliases || !cpu_has_ic_fills_f_dc)
                __flush_dcache_page(page);
 
 }
@@ -47,8 +46,13 @@ static inline void flush_dcache_page(struct page *page)
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
-extern void (*flush_icache_page)(struct vm_area_struct *vma,
+extern void (*__flush_icache_page)(struct vm_area_struct *vma,
        struct page *page);
+static inline void flush_icache_page(struct vm_area_struct *vma,
+       struct page *page)
+{
+}
+
 extern void (*flush_icache_range)(unsigned long start, unsigned long end);
 #define flush_cache_vmap(start, end)           flush_cache_all()
 #define flush_cache_vunmap(start, end)         flush_cache_all()
@@ -60,7 +64,7 @@ static inline void copy_to_user_page(struct vm_area_struct *vma,
        if (cpu_has_dc_aliases)
                flush_cache_page(vma, vaddr, page_to_pfn(page));
        memcpy(dst, src, len);
-       flush_icache_page(vma, page);
+       __flush_icache_page(vma, page);
 }
 
 static inline void copy_from_user_page(struct vm_area_struct *vma,
index 787220e6c1fc4f187b855de989f24b0e4f63c441..00a50ec1c19fd6426bd57732aad5e2bdd64e7807 100644 (file)
@@ -25,8 +25,6 @@
 
 #define F_SETOWN       24      /*  for sockets. */
 #define F_GETOWN       23      /*  for sockets. */
-#define F_SETSIG       10      /*  for sockets. */
-#define F_GETSIG       11      /*  for sockets. */
 
 #ifndef __mips64
 #define F_GETLK64      33      /*  using 'struct flock64' */
diff --git a/include/asm-mips/galileo-boards/gt96100.h b/include/asm-mips/galileo-boards/gt96100.h
deleted file mode 100644 (file)
index aabd1b6..0000000
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright 2000 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *             stevel@mvista.com or source@mvista.com
- *
- *  This program is free software; you can distribute 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 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.
- *
- * Register offsets of the MIPS GT96100 Advanced Communication Controller.
- */
-#ifndef _GT96100_H
-#define _GT96100_H
-
-/*
- * Galileo GT96100 internal register base.
- */
-#define MIPS_GT96100_BASE (KSEG1ADDR(0x14000000))
-
-#define GT96100_WRITE(ofs, data) \
-    *(volatile u32 *)(MIPS_GT96100_BASE+ofs) = cpu_to_le32(data)
-#define GT96100_READ(ofs) \
-    le32_to_cpu(*(volatile u32 *)(MIPS_GT96100_BASE+ofs))
-
-#define GT96100_ETH_IO_SIZE 0x4000
-
-/************************************************************************
- *  Register offset addresses follow
- ************************************************************************/
-
-/* CPU Interface Control Registers */
-#define GT96100_CPU_INTERF_CONFIG 0x000000
-
-/* Ethernet Ports */
-#define GT96100_ETH_PHY_ADDR_REG             0x080800
-#define GT96100_ETH_SMI_REG                  0x080810
-/*
-  These are offsets to port 0 registers. Add GT96100_ETH_IO_SIZE to
-  get offsets to port 1 registers.
-*/
-#define GT96100_ETH_PORT_CONFIG          0x084800
-#define GT96100_ETH_PORT_CONFIG_EXT      0x084808
-#define GT96100_ETH_PORT_COMM            0x084810
-#define GT96100_ETH_PORT_STATUS          0x084818
-#define GT96100_ETH_SER_PARAM            0x084820
-#define GT96100_ETH_HASH_TBL_PTR         0x084828
-#define GT96100_ETH_FLOW_CNTRL_SRC_ADDR_L    0x084830
-#define GT96100_ETH_FLOW_CNTRL_SRC_ADDR_H    0x084838
-#define GT96100_ETH_SDMA_CONFIG          0x084840
-#define GT96100_ETH_SDMA_COMM            0x084848
-#define GT96100_ETH_INT_CAUSE            0x084850
-#define GT96100_ETH_INT_MASK             0x084858
-#define GT96100_ETH_1ST_RX_DESC_PTR0         0x084880
-#define GT96100_ETH_1ST_RX_DESC_PTR1         0x084884
-#define GT96100_ETH_1ST_RX_DESC_PTR2         0x084888
-#define GT96100_ETH_1ST_RX_DESC_PTR3         0x08488C
-#define GT96100_ETH_CURR_RX_DESC_PTR0        0x0848A0
-#define GT96100_ETH_CURR_RX_DESC_PTR1        0x0848A4
-#define GT96100_ETH_CURR_RX_DESC_PTR2        0x0848A8
-#define GT96100_ETH_CURR_RX_DESC_PTR3        0x0848AC
-#define GT96100_ETH_CURR_TX_DESC_PTR0        0x0848E0
-#define GT96100_ETH_CURR_TX_DESC_PTR1        0x0848E4
-#define GT96100_ETH_MIB_COUNT_BASE           0x085800
-
-/* SDMAs */
-#define GT96100_SDMA_GROUP_CONFIG           0x101AF0
-/* SDMA Group 0 */
-#define GT96100_SDMA_G0_CHAN0_CONFIG        0x000900
-#define GT96100_SDMA_G0_CHAN0_COMM          0x000908
-#define GT96100_SDMA_G0_CHAN0_RX_DESC_BASE      0x008900
-#define GT96100_SDMA_G0_CHAN0_CURR_RX_DESC_PTR  0x008910
-#define GT96100_SDMA_G0_CHAN0_TX_DESC_BASE      0x00C900
-#define GT96100_SDMA_G0_CHAN0_CURR_TX_DESC_PTR  0x00C910
-#define GT96100_SDMA_G0_CHAN0_1ST_TX_DESC_PTR   0x00C914
-#define GT96100_SDMA_G0_CHAN1_CONFIG        0x010900
-#define GT96100_SDMA_G0_CHAN1_COMM          0x010908
-#define GT96100_SDMA_G0_CHAN1_RX_DESC_BASE      0x018900
-#define GT96100_SDMA_G0_CHAN1_CURR_RX_DESC_PTR  0x018910
-#define GT96100_SDMA_G0_CHAN1_TX_DESC_BASE      0x01C900
-#define GT96100_SDMA_G0_CHAN1_CURR_TX_DESC_PTR  0x01C910
-#define GT96100_SDMA_G0_CHAN1_1ST_TX_DESC_PTR   0x01C914
-#define GT96100_SDMA_G0_CHAN2_CONFIG        0x020900
-#define GT96100_SDMA_G0_CHAN2_COMM          0x020908
-#define GT96100_SDMA_G0_CHAN2_RX_DESC_BASE      0x028900
-#define GT96100_SDMA_G0_CHAN2_CURR_RX_DESC_PTR  0x028910
-#define GT96100_SDMA_G0_CHAN2_TX_DESC_BASE      0x02C900
-#define GT96100_SDMA_G0_CHAN2_CURR_TX_DESC_PTR  0x02C910
-#define GT96100_SDMA_G0_CHAN2_1ST_TX_DESC_PTR   0x02C914
-#define GT96100_SDMA_G0_CHAN3_CONFIG        0x030900
-#define GT96100_SDMA_G0_CHAN3_COMM          0x030908
-#define GT96100_SDMA_G0_CHAN3_RX_DESC_BASE      0x038900
-#define GT96100_SDMA_G0_CHAN3_CURR_RX_DESC_PTR  0x038910
-#define GT96100_SDMA_G0_CHAN3_TX_DESC_BASE      0x03C900
-#define GT96100_SDMA_G0_CHAN3_CURR_TX_DESC_PTR  0x03C910
-#define GT96100_SDMA_G0_CHAN3_1ST_TX_DESC_PTR   0x03C914
-#define GT96100_SDMA_G0_CHAN4_CONFIG        0x040900
-#define GT96100_SDMA_G0_CHAN4_COMM          0x040908
-#define GT96100_SDMA_G0_CHAN4_RX_DESC_BASE      0x048900
-#define GT96100_SDMA_G0_CHAN4_CURR_RX_DESC_PTR  0x048910
-#define GT96100_SDMA_G0_CHAN4_TX_DESC_BASE      0x04C900
-#define GT96100_SDMA_G0_CHAN4_CURR_TX_DESC_PTR  0x04C910
-#define GT96100_SDMA_G0_CHAN4_1ST_TX_DESC_PTR   0x04C914
-#define GT96100_SDMA_G0_CHAN5_CONFIG        0x050900
-#define GT96100_SDMA_G0_CHAN5_COMM          0x050908
-#define GT96100_SDMA_G0_CHAN5_RX_DESC_BASE      0x058900
-#define GT96100_SDMA_G0_CHAN5_CURR_RX_DESC_PTR  0x058910
-#define GT96100_SDMA_G0_CHAN5_TX_DESC_BASE      0x05C900
-#define GT96100_SDMA_G0_CHAN5_CURR_TX_DESC_PTR  0x05C910
-#define GT96100_SDMA_G0_CHAN5_1ST_TX_DESC_PTR   0x05C914
-#define GT96100_SDMA_G0_CHAN6_CONFIG        0x060900
-#define GT96100_SDMA_G0_CHAN6_COMM          0x060908
-#define GT96100_SDMA_G0_CHAN6_RX_DESC_BASE      0x068900
-#define GT96100_SDMA_G0_CHAN6_CURR_RX_DESC_PTR  0x068910
-#define GT96100_SDMA_G0_CHAN6_TX_DESC_BASE      0x06C900
-#define GT96100_SDMA_G0_CHAN6_CURR_TX_DESC_PTR  0x06C910
-#define GT96100_SDMA_G0_CHAN6_1ST_TX_DESC_PTR   0x06C914
-#define GT96100_SDMA_G0_CHAN7_CONFIG        0x070900
-#define GT96100_SDMA_G0_CHAN7_COMM          0x070908
-#define GT96100_SDMA_G0_CHAN7_RX_DESC_BASE      0x078900
-#define GT96100_SDMA_G0_CHAN7_CURR_RX_DESC_PTR  0x078910
-#define GT96100_SDMA_G0_CHAN7_TX_DESC_BASE      0x07C900
-#define GT96100_SDMA_G0_CHAN7_CURR_TX_DESC_PTR  0x07C910
-#define GT96100_SDMA_G0_CHAN7_1ST_TX_DESC_PTR   0x07C914
-/* SDMA Group 1 */
-#define GT96100_SDMA_G1_CHAN0_CONFIG        0x100900
-#define GT96100_SDMA_G1_CHAN0_COMM          0x100908
-#define GT96100_SDMA_G1_CHAN0_RX_DESC_BASE      0x108900
-#define GT96100_SDMA_G1_CHAN0_CURR_RX_DESC_PTR  0x108910
-#define GT96100_SDMA_G1_CHAN0_TX_DESC_BASE      0x10C900
-#define GT96100_SDMA_G1_CHAN0_CURR_TX_DESC_PTR  0x10C910
-#define GT96100_SDMA_G1_CHAN0_1ST_TX_DESC_PTR   0x10C914
-#define GT96100_SDMA_G1_CHAN1_CONFIG        0x110900
-#define GT96100_SDMA_G1_CHAN1_COMM          0x110908
-#define GT96100_SDMA_G1_CHAN1_RX_DESC_BASE      0x118900
-#define GT96100_SDMA_G1_CHAN1_CURR_RX_DESC_PTR  0x118910
-#define GT96100_SDMA_G1_CHAN1_TX_DESC_BASE      0x11C900
-#define GT96100_SDMA_G1_CHAN1_CURR_TX_DESC_PTR  0x11C910
-#define GT96100_SDMA_G1_CHAN1_1ST_TX_DESC_PTR   0x11C914
-#define GT96100_SDMA_G1_CHAN2_CONFIG        0x120900
-#define GT96100_SDMA_G1_CHAN2_COMM          0x120908
-#define GT96100_SDMA_G1_CHAN2_RX_DESC_BASE      0x128900
-#define GT96100_SDMA_G1_CHAN2_CURR_RX_DESC_PTR  0x128910
-#define GT96100_SDMA_G1_CHAN2_TX_DESC_BASE      0x12C900
-#define GT96100_SDMA_G1_CHAN2_CURR_TX_DESC_PTR  0x12C910
-#define GT96100_SDMA_G1_CHAN2_1ST_TX_DESC_PTR   0x12C914
-#define GT96100_SDMA_G1_CHAN3_CONFIG        0x130900
-#define GT96100_SDMA_G1_CHAN3_COMM          0x130908
-#define GT96100_SDMA_G1_CHAN3_RX_DESC_BASE      0x138900
-#define GT96100_SDMA_G1_CHAN3_CURR_RX_DESC_PTR  0x138910
-#define GT96100_SDMA_G1_CHAN3_TX_DESC_BASE      0x13C900
-#define GT96100_SDMA_G1_CHAN3_CURR_TX_DESC_PTR  0x13C910
-#define GT96100_SDMA_G1_CHAN3_1ST_TX_DESC_PTR   0x13C914
-#define GT96100_SDMA_G1_CHAN4_CONFIG        0x140900
-#define GT96100_SDMA_G1_CHAN4_COMM          0x140908
-#define GT96100_SDMA_G1_CHAN4_RX_DESC_BASE      0x148900
-#define GT96100_SDMA_G1_CHAN4_CURR_RX_DESC_PTR  0x148910
-#define GT96100_SDMA_G1_CHAN4_TX_DESC_BASE      0x14C900
-#define GT96100_SDMA_G1_CHAN4_CURR_TX_DESC_PTR  0x14C910
-#define GT96100_SDMA_G1_CHAN4_1ST_TX_DESC_PTR   0x14C914
-#define GT96100_SDMA_G1_CHAN5_CONFIG        0x150900
-#define GT96100_SDMA_G1_CHAN5_COMM          0x150908
-#define GT96100_SDMA_G1_CHAN5_RX_DESC_BASE      0x158900
-#define GT96100_SDMA_G1_CHAN5_CURR_RX_DESC_PTR  0x158910
-#define GT96100_SDMA_G1_CHAN5_TX_DESC_BASE      0x15C900
-#define GT96100_SDMA_G1_CHAN5_CURR_TX_DESC_PTR  0x15C910
-#define GT96100_SDMA_G1_CHAN5_1ST_TX_DESC_PTR   0x15C914
-#define GT96100_SDMA_G1_CHAN6_CONFIG        0x160900
-#define GT96100_SDMA_G1_CHAN6_COMM          0x160908
-#define GT96100_SDMA_G1_CHAN6_RX_DESC_BASE      0x168900
-#define GT96100_SDMA_G1_CHAN6_CURR_RX_DESC_PTR  0x168910
-#define GT96100_SDMA_G1_CHAN6_TX_DESC_BASE      0x16C900
-#define GT96100_SDMA_G1_CHAN6_CURR_TX_DESC_PTR  0x16C910
-#define GT96100_SDMA_G1_CHAN6_1ST_TX_DESC_PTR   0x16C914
-#define GT96100_SDMA_G1_CHAN7_CONFIG        0x170900
-#define GT96100_SDMA_G1_CHAN7_COMM          0x170908
-#define GT96100_SDMA_G1_CHAN7_RX_DESC_BASE      0x178900
-#define GT96100_SDMA_G1_CHAN7_CURR_RX_DESC_PTR  0x178910
-#define GT96100_SDMA_G1_CHAN7_TX_DESC_BASE      0x17C900
-#define GT96100_SDMA_G1_CHAN7_CURR_TX_DESC_PTR  0x17C910
-#define GT96100_SDMA_G1_CHAN7_1ST_TX_DESC_PTR   0x17C914
-/*  MPSCs  */
-#define GT96100_MPSC0_MAIN_CONFIG_LOW   0x000A00
-#define GT96100_MPSC0_MAIN_CONFIG_HIGH  0x000A04
-#define GT96100_MPSC0_PROTOCOL_CONFIG   0x000A08
-#define GT96100_MPSC_CHAN0_REG1         0x000A0C
-#define GT96100_MPSC_CHAN0_REG2         0x000A10
-#define GT96100_MPSC_CHAN0_REG3         0x000A14
-#define GT96100_MPSC_CHAN0_REG4         0x000A18
-#define GT96100_MPSC_CHAN0_REG5         0x000A1C
-#define GT96100_MPSC_CHAN0_REG6         0x000A20
-#define GT96100_MPSC_CHAN0_REG7         0x000A24
-#define GT96100_MPSC_CHAN0_REG8         0x000A28
-#define GT96100_MPSC_CHAN0_REG9         0x000A2C
-#define GT96100_MPSC_CHAN0_REG10        0x000A30
-#define GT96100_MPSC_CHAN0_REG11        0x000A34
-#define GT96100_MPSC1_MAIN_CONFIG_LOW   0x008A00
-#define GT96100_MPSC1_MAIN_CONFIG_HIGH  0x008A04
-#define GT96100_MPSC1_PROTOCOL_CONFIG   0x008A08
-#define GT96100_MPSC_CHAN1_REG1         0x008A0C
-#define GT96100_MPSC_CHAN1_REG2         0x008A10
-#define GT96100_MPSC_CHAN1_REG3         0x008A14
-#define GT96100_MPSC_CHAN1_REG4         0x008A18
-#define GT96100_MPSC_CHAN1_REG5         0x008A1C
-#define GT96100_MPSC_CHAN1_REG6         0x008A20
-#define GT96100_MPSC_CHAN1_REG7         0x008A24
-#define GT96100_MPSC_CHAN1_REG8         0x008A28
-#define GT96100_MPSC_CHAN1_REG9         0x008A2C
-#define GT96100_MPSC_CHAN1_REG10        0x008A30
-#define GT96100_MPSC_CHAN1_REG11        0x008A34
-#define GT96100_MPSC2_MAIN_CONFIG_LOW   0x010A00
-#define GT96100_MPSC2_MAIN_CONFIG_HIGH  0x010A04
-#define GT96100_MPSC2_PROTOCOL_CONFIG   0x010A08
-#define GT96100_MPSC_CHAN2_REG1         0x010A0C
-#define GT96100_MPSC_CHAN2_REG2         0x010A10
-#define GT96100_MPSC_CHAN2_REG3         0x010A14
-#define GT96100_MPSC_CHAN2_REG4         0x010A18
-#define GT96100_MPSC_CHAN2_REG5         0x010A1C
-#define GT96100_MPSC_CHAN2_REG6         0x010A20
-#define GT96100_MPSC_CHAN2_REG7         0x010A24
-#define GT96100_MPSC_CHAN2_REG8         0x010A28
-#define GT96100_MPSC_CHAN2_REG9         0x010A2C
-#define GT96100_MPSC_CHAN2_REG10        0x010A30
-#define GT96100_MPSC_CHAN2_REG11        0x010A34
-#define GT96100_MPSC3_MAIN_CONFIG_LOW   0x018A00
-#define GT96100_MPSC3_MAIN_CONFIG_HIGH  0x018A04
-#define GT96100_MPSC3_PROTOCOL_CONFIG   0x018A08
-#define GT96100_MPSC_CHAN3_REG1         0x018A0C
-#define GT96100_MPSC_CHAN3_REG2         0x018A10
-#define GT96100_MPSC_CHAN3_REG3         0x018A14
-#define GT96100_MPSC_CHAN3_REG4         0x018A18
-#define GT96100_MPSC_CHAN3_REG5         0x018A1C
-#define GT96100_MPSC_CHAN3_REG6         0x018A20
-#define GT96100_MPSC_CHAN3_REG7         0x018A24
-#define GT96100_MPSC_CHAN3_REG8         0x018A28
-#define GT96100_MPSC_CHAN3_REG9         0x018A2C
-#define GT96100_MPSC_CHAN3_REG10        0x018A30
-#define GT96100_MPSC_CHAN3_REG11        0x018A34
-#define GT96100_MPSC4_MAIN_CONFIG_LOW   0x020A00
-#define GT96100_MPSC4_MAIN_CONFIG_HIGH  0x020A04
-#define GT96100_MPSC4_PROTOCOL_CONFIG   0x020A08
-#define GT96100_MPSC_CHAN4_REG1         0x020A0C
-#define GT96100_MPSC_CHAN4_REG2         0x020A10
-#define GT96100_MPSC_CHAN4_REG3         0x020A14
-#define GT96100_MPSC_CHAN4_REG4         0x020A18
-#define GT96100_MPSC_CHAN4_REG5         0x020A1C
-#define GT96100_MPSC_CHAN4_REG6         0x020A20
-#define GT96100_MPSC_CHAN4_REG7         0x020A24
-#define GT96100_MPSC_CHAN4_REG8         0x020A28
-#define GT96100_MPSC_CHAN4_REG9         0x020A2C
-#define GT96100_MPSC_CHAN4_REG10        0x020A30
-#define GT96100_MPSC_CHAN4_REG11        0x020A34
-#define GT96100_MPSC5_MAIN_CONFIG_LOW   0x028A00
-#define GT96100_MPSC5_MAIN_CONFIG_HIGH  0x028A04
-#define GT96100_MPSC5_PROTOCOL_CONFIG   0x028A08
-#define GT96100_MPSC_CHAN5_REG1         0x028A0C
-#define GT96100_MPSC_CHAN5_REG2         0x028A10
-#define GT96100_MPSC_CHAN5_REG3         0x028A14
-#define GT96100_MPSC_CHAN5_REG4         0x028A18
-#define GT96100_MPSC_CHAN5_REG5         0x028A1C
-#define GT96100_MPSC_CHAN5_REG6         0x028A20
-#define GT96100_MPSC_CHAN5_REG7         0x028A24
-#define GT96100_MPSC_CHAN5_REG8         0x028A28
-#define GT96100_MPSC_CHAN5_REG9         0x028A2C
-#define GT96100_MPSC_CHAN5_REG10        0x028A30
-#define GT96100_MPSC_CHAN5_REG11        0x028A34
-#define GT96100_MPSC6_MAIN_CONFIG_LOW   0x030A00
-#define GT96100_MPSC6_MAIN_CONFIG_HIGH  0x030A04
-#define GT96100_MPSC6_PROTOCOL_CONFIG   0x030A08
-#define GT96100_MPSC_CHAN6_REG1         0x030A0C
-#define GT96100_MPSC_CHAN6_REG2         0x030A10
-#define GT96100_MPSC_CHAN6_REG3         0x030A14
-#define GT96100_MPSC_CHAN6_REG4         0x030A18
-#define GT96100_MPSC_CHAN6_REG5         0x030A1C
-#define GT96100_MPSC_CHAN6_REG6         0x030A20
-#define GT96100_MPSC_CHAN6_REG7         0x030A24
-#define GT96100_MPSC_CHAN6_REG8         0x030A28
-#define GT96100_MPSC_CHAN6_REG9         0x030A2C
-#define GT96100_MPSC_CHAN6_REG10        0x030A30
-#define GT96100_MPSC_CHAN6_REG11        0x030A34
-#define GT96100_MPSC7_MAIN_CONFIG_LOW   0x038A00
-#define GT96100_MPSC7_MAIN_CONFIG_HIGH  0x038A04
-#define GT96100_MPSC7_PROTOCOL_CONFIG   0x038A08
-#define GT96100_MPSC_CHAN7_REG1         0x038A0C
-#define GT96100_MPSC_CHAN7_REG2         0x038A10
-#define GT96100_MPSC_CHAN7_REG3         0x038A14
-#define GT96100_MPSC_CHAN7_REG4         0x038A18
-#define GT96100_MPSC_CHAN7_REG5         0x038A1C
-#define GT96100_MPSC_CHAN7_REG6         0x038A20
-#define GT96100_MPSC_CHAN7_REG7         0x038A24
-#define GT96100_MPSC_CHAN7_REG8         0x038A28
-#define GT96100_MPSC_CHAN7_REG9         0x038A2C
-#define GT96100_MPSC_CHAN7_REG10        0x038A30
-#define GT96100_MPSC_CHAN7_REG11        0x038A34
-/*  FlexTDMs  */
-/* TDPR0 - Transmit Dual Port RAM. block size 0xff */
-#define GT96100_FXTDM0_TDPR0_BLK0_BASE  0x000B00
-#define GT96100_FXTDM0_TDPR0_BLK1_BASE  0x001B00
-#define GT96100_FXTDM0_TDPR0_BLK2_BASE  0x002B00
-#define GT96100_FXTDM0_TDPR0_BLK3_BASE  0x003B00
-/* RDPR0 - Receive Dual Port RAM. block size 0xff */
-#define GT96100_FXTDM0_RDPR0_BLK0_BASE  0x004B00
-#define GT96100_FXTDM0_RDPR0_BLK1_BASE  0x005B00
-#define GT96100_FXTDM0_RDPR0_BLK2_BASE  0x006B00
-#define GT96100_FXTDM0_RDPR0_BLK3_BASE  0x007B00
-#define GT96100_FXTDM0_TX_READ_PTR      0x008B00
-#define GT96100_FXTDM0_RX_READ_PTR      0x008B04
-#define GT96100_FXTDM0_CONFIG       0x008B08
-#define GT96100_FXTDM0_AUX_CHANA_TX 0x008B0C
-#define GT96100_FXTDM0_AUX_CHANA_RX 0x008B10
-#define GT96100_FXTDM0_AUX_CHANB_TX 0x008B14
-#define GT96100_FXTDM0_AUX_CHANB_RX 0x008B18
-#define GT96100_FXTDM1_TDPR1_BLK0_BASE  0x010B00
-#define GT96100_FXTDM1_TDPR1_BLK1_BASE  0x011B00
-#define GT96100_FXTDM1_TDPR1_BLK2_BASE  0x012B00
-#define GT96100_FXTDM1_TDPR1_BLK3_BASE  0x013B00
-#define GT96100_FXTDM1_RDPR1_BLK0_BASE  0x014B00
-#define GT96100_FXTDM1_RDPR1_BLK1_BASE  0x015B00
-#define GT96100_FXTDM1_RDPR1_BLK2_BASE  0x016B00
-#define GT96100_FXTDM1_RDPR1_BLK3_BASE  0x017B00
-#define GT96100_FXTDM1_TX_READ_PTR      0x018B00
-#define GT96100_FXTDM1_RX_READ_PTR      0x018B04
-#define GT96100_FXTDM1_CONFIG       0x018B08
-#define GT96100_FXTDM1_AUX_CHANA_TX 0x018B0C
-#define GT96100_FXTDM1_AUX_CHANA_RX 0x018B10
-#define GT96100_FLTDM1_AUX_CHANB_TX 0x018B14
-#define GT96100_FLTDM1_AUX_CHANB_RX 0x018B18
-#define GT96100_FLTDM2_TDPR2_BLK0_BASE  0x020B00
-#define GT96100_FLTDM2_TDPR2_BLK1_BASE  0x021B00
-#define GT96100_FLTDM2_TDPR2_BLK2_BASE  0x022B00
-#define GT96100_FLTDM2_TDPR2_BLK3_BASE  0x023B00
-#define GT96100_FLTDM2_RDPR2_BLK0_BASE  0x024B00
-#define GT96100_FLTDM2_RDPR2_BLK1_BASE  0x025B00
-#define GT96100_FLTDM2_RDPR2_BLK2_BASE  0x026B00
-#define GT96100_FLTDM2_RDPR2_BLK3_BASE  0x027B00
-#define GT96100_FLTDM2_TX_READ_PTR      0x028B00
-#define GT96100_FLTDM2_RX_READ_PTR      0x028B04
-#define GT96100_FLTDM2_CONFIG       0x028B08
-#define GT96100_FLTDM2_AUX_CHANA_TX 0x028B0C
-#define GT96100_FLTDM2_AUX_CHANA_RX 0x028B10
-#define GT96100_FLTDM2_AUX_CHANB_TX 0x028B14
-#define GT96100_FLTDM2_AUX_CHANB_RX 0x028B18
-#define GT96100_FLTDM3_TDPR3_BLK0_BASE  0x030B00
-#define GT96100_FLTDM3_TDPR3_BLK1_BASE  0x031B00
-#define GT96100_FLTDM3_TDPR3_BLK2_BASE  0x032B00
-#define GT96100_FLTDM3_TDPR3_BLK3_BASE  0x033B00
-#define GT96100_FXTDM3_RDPR3_BLK0_BASE  0x034B00
-#define GT96100_FXTDM3_RDPR3_BLK1_BASE  0x035B00
-#define GT96100_FXTDM3_RDPR3_BLK2_BASE  0x036B00
-#define GT96100_FXTDM3_RDPR3_BLK3_BASE  0x037B00
-#define GT96100_FXTDM3_TX_READ_PTR      0x038B00
-#define GT96100_FXTDM3_RX_READ_PTR      0x038B04
-#define GT96100_FXTDM3_CONFIG       0x038B08
-#define GT96100_FXTDM3_AUX_CHANA_TX 0x038B0C
-#define GT96100_FXTDM3_AUX_CHANA_RX 0x038B10
-#define GT96100_FXTDM3_AUX_CHANB_TX 0x038B14
-#define GT96100_FXTDM3_AUX_CHANB_RX 0x038B18
-/*  Baud Rate Generators  */
-#define GT96100_BRG0_CONFIG     0x102A00
-#define GT96100_BRG0_BAUD_TUNE  0x102A04
-#define GT96100_BRG1_CONFIG     0x102A08
-#define GT96100_BRG1_BAUD_TUNE  0x102A0C
-#define GT96100_BRG2_CONFIG     0x102A10
-#define GT96100_BRG2_BAUD_TUNE  0x102A14
-#define GT96100_BRG3_CONFIG     0x102A18
-#define GT96100_BRG3_BAUD_TUNE  0x102A1C
-#define GT96100_BRG4_CONFIG     0x102A20
-#define GT96100_BRG4_BAUD_TUNE  0x102A24
-#define GT96100_BRG5_CONFIG     0x102A28
-#define GT96100_BRG5_BAUD_TUNE  0x102A2C
-#define GT96100_BRG6_CONFIG     0x102A30
-#define GT96100_BRG6_BAUD_TUNE  0x102A34
-#define GT96100_BRG7_CONFIG     0x102A38
-#define GT96100_BRG7_BAUD_TUNE  0x102A3C
-/*  Routing Registers  */
-#define GT96100_ROUTE_MAIN      0x101A00
-#define GT96100_ROUTE_RX_CLOCK  0x101A10
-#define GT96100_ROUTE_TX_CLOCK  0x101A20
-/*  General Purpose Ports  */
-#define GT96100_GPP_CONFIG0     0x100A00
-#define GT96100_GPP_CONFIG1     0x100A04
-#define GT96100_GPP_CONFIG2     0x100A08
-#define GT96100_GPP_CONFIG3     0x100A0C
-#define GT96100_GPP_IO0         0x100A20
-#define GT96100_GPP_IO1         0x100A24
-#define GT96100_GPP_IO2         0x100A28
-#define GT96100_GPP_IO3         0x100A2C
-#define GT96100_GPP_DATA0       0x100A40
-#define GT96100_GPP_DATA1       0x100A44
-#define GT96100_GPP_DATA2       0x100A48
-#define GT96100_GPP_DATA3       0x100A4C
-#define GT96100_GPP_LEVEL0      0x100A60
-#define GT96100_GPP_LEVEL1      0x100A64
-#define GT96100_GPP_LEVEL2      0x100A68
-#define GT96100_GPP_LEVEL3      0x100A6C
-/*  Watchdog  */
-#define GT96100_WD_CONFIG   0x101A80
-#define GT96100_WD_VALUE    0x101A84
-/* Communication Unit Arbiter  */
-#define GT96100_COMM_UNIT_ARBTR_CONFIG 0x101AC0
-/*  PCI Arbiters  */
-#define GT96100_PCI0_ARBTR_CONFIG 0x101AE0
-#define GT96100_PCI1_ARBTR_CONFIG 0x101AE4
-/* CIU Arbiter */
-#define GT96100_CIU_ARBITER_CONFIG 0x101AC0
-/* Interrupt Controller */
-#define GT96100_MAIN_CAUSE     0x000C18
-#define GT96100_INT0_MAIN_MASK 0x000C1C
-#define GT96100_INT1_MAIN_MASK 0x000C24
-#define GT96100_HIGH_CAUSE     0x000C98
-#define GT96100_INT0_HIGH_MASK 0x000C9C
-#define GT96100_INT1_HIGH_MASK 0x000CA4
-#define GT96100_INT0_SELECT    0x000C70
-#define GT96100_INT1_SELECT    0x000C74
-#define GT96100_SERIAL_CAUSE   0x103A00
-#define GT96100_SERINT0_MASK   0x103A80
-#define GT96100_SERINT1_MASK   0x103A88
-
-#endif /*  _GT96100_H */
index 25f5e8a4177d1378fb60645483a4e364c1e879c1..0fe02945feba0b8a18868126a99d977558294d33 100644 (file)
 
 
 #ifdef __ASSEMBLY__
-
-       .macro  _ssnop
-       sll     $0, $0, 1
-       .endm
-
-       .macro  _ehb
-       sll     $0, $0, 3
-       .endm
-
-/*
- * RM9000 hazards.  When the JTLB is updated by tlbwi or tlbwr, a subsequent
- * use of the JTLB for instructions should not occur for 4 cpu cycles and use
- * for data translations should not occur for 3 cpu cycles.
- */
-#ifdef CONFIG_CPU_RM9000
-
-       .macro  mtc0_tlbw_hazard
-       .set    push
-       .set    mips32
-       _ssnop; _ssnop; _ssnop; _ssnop
-       .set    pop
-       .endm
-
-       .macro  tlbw_eret_hazard
-       .set    push
-       .set    mips32
-       _ssnop; _ssnop; _ssnop; _ssnop
-       .set    pop
-       .endm
-
+#define ASMMACRO(name, code...) .macro name; code; .endm
 #else
 
-/*
- * The taken branch will result in a two cycle penalty for the two killed
- * instructions on R4000 / R4400.  Other processors only have a single cycle
- * hazard so this is nice trick to have an optimal code for a range of
- * processors.
- */
-       .macro  mtc0_tlbw_hazard
-       b       . + 8
-       .endm
+#define ASMMACRO(name, code...)                                                \
+__asm__(".macro " #name "; " #code "; .endm");                         \
+                                                                       \
+static inline void name(void)                                          \
+{                                                                      \
+       __asm__ __volatile__ (#name);                                   \
+}
 
-       .macro  tlbw_eret_hazard
-       .endm
 #endif
 
+ASMMACRO(_ssnop,
+        sll    $0, $0, 1
+       )
+
+ASMMACRO(_ehb,
+        sll    $0, $0, 3
+       )
+
 /*
- * mtc0->mfc0 hazard
- * The 24K has a 2 cycle mtc0/mfc0 execution hazard.
- * It is a MIPS32R2 processor so ehb will clear the hazard.
+ * TLB hazards
  */
+#if defined(CONFIG_CPU_MIPSR2)
 
-#ifdef CONFIG_CPU_MIPSR2
 /*
- * Use a macro for ehb unless explicit support for MIPSR2 is enabled
+ * MIPSR2 defines ehb for hazard avoidance
  */
 
-#define irq_enable_hazard                                              \
+ASMMACRO(mtc0_tlbw_hazard,
+        _ehb
+       )
+ASMMACRO(tlbw_use_hazard,
+        _ehb
+       )
+ASMMACRO(tlb_probe_hazard,
+        _ehb
+       )
+ASMMACRO(irq_enable_hazard,
+       )
+ASMMACRO(irq_disable_hazard,
        _ehb
-
-#define irq_disable_hazard                                             \
-       _ehb
-
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
-
+       )
+ASMMACRO(back_to_back_c0_hazard,
+        _ehb
+       )
 /*
- * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
+ * gcc has a tradition of misscompiling the previous construct using the
+ * address of a label as argument to inline assembler.  Gas otoh has the
+ * annoying difference between la and dla which are only usable for 32-bit
+ * rsp. 64-bit code, so can't be used without conditional compilation.
+ * The alterantive is switching the assembler to 64-bit code which happens
+ * to work right even for 32-bit code ...
  */
+#define instruction_hazard()                                           \
+do {                                                                   \
+       unsigned long tmp;                                              \
+                                                                       \
+       __asm__ __volatile__(                                           \
+       "       .set    mips64r2                                \n"     \
+       "       dla     %0, 1f                                  \n"     \
+       "       jr.hb   %0                                      \n"     \
+       "       .set    mips0                                   \n"     \
+       "1:                                                     \n"     \
+       : "=r" (tmp));                                                  \
+} while (0)
 
-#define irq_enable_hazard
-
-#define irq_disable_hazard
-
-#else
+#elif defined(CONFIG_CPU_R10000)
 
 /*
- * Classic MIPS needs 1 - 3 nops or ssnops
+ * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
  */
-#define irq_enable_hazard
-#define irq_disable_hazard                                             \
-       _ssnop; _ssnop; _ssnop
 
-#endif
-
-#else /* __ASSEMBLY__ */
-
-__asm__(
-       "       .macro  _ssnop                                  \n"
-       "       sll     $0, $0, 1                               \n"
-       "       .endm                                           \n"
-       "                                                       \n"
-       "       .macro  _ehb                                    \n"
-       "       sll     $0, $0, 3                               \n"
-       "       .endm                                           \n");
+ASMMACRO(mtc0_tlbw_hazard,
+       )
+ASMMACRO(tlbw_use_hazard,
+       )
+ASMMACRO(tlb_probe_hazard,
+       )
+ASMMACRO(irq_enable_hazard,
+       )
+ASMMACRO(irq_disable_hazard,
+       )
+ASMMACRO(back_to_back_c0_hazard,
+       )
+#define instruction_hazard() do { } while (0)
 
-#ifdef CONFIG_CPU_RM9000
+#elif defined(CONFIG_CPU_RM9000)
 
 /*
  * RM9000 hazards.  When the JTLB is updated by tlbwi or tlbwr, a subsequent
@@ -115,176 +108,73 @@ __asm__(
  * for data translations should not occur for 3 cpu cycles.
  */
 
-#define mtc0_tlbw_hazard()                                             \
-       __asm__ __volatile__(                                           \
-       "       .set    mips32                                  \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       .set    mips0                                   \n")
-
-#define tlbw_use_hazard()                                              \
-       __asm__ __volatile__(                                           \
-       "       .set    mips32                                  \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       _ssnop                                          \n"     \
-       "       .set    mips0                                   \n")
-
-#else
-
-/*
- * Overkill warning ...
- */
-#define mtc0_tlbw_hazard()                                             \
-       __asm__ __volatile__(                                           \
-       "       .set    noreorder                               \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       .set    reorder                                 \n")
-
-#define tlbw_use_hazard()                                              \
-       __asm__ __volatile__(                                           \
-       "       .set    noreorder                               \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       nop                                             \n"     \
-       "       .set    reorder                                 \n")
-
-#endif
-
-/*
- * Interrupt enable/disable hazards
- * Some processors have hazards when modifying
- * the status register to change the interrupt state
- */
-
-#ifdef CONFIG_CPU_MIPSR2
-
-__asm__("      .macro  irq_enable_hazard                       \n"
-       "       _ehb                                            \n"
-       "       .endm                                           \n"
-       "                                                       \n"
-       "       .macro  irq_disable_hazard                      \n"
-       "       _ehb                                            \n"
-       "       .endm                                           \n");
+ASMMACRO(mtc0_tlbw_hazard,
+        _ssnop; _ssnop; _ssnop; _ssnop
+       )
+ASMMACRO(tlbw_use_hazard,
+        _ssnop; _ssnop; _ssnop; _ssnop
+       )
+ASMMACRO(tlb_probe_hazard,
+        _ssnop; _ssnop; _ssnop; _ssnop
+       )
+ASMMACRO(irq_enable_hazard,
+       )
+ASMMACRO(irq_disable_hazard,
+       )
+ASMMACRO(back_to_back_c0_hazard,
+       )
+#define instruction_hazard() do { } while (0)
 
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
+#elif defined(CONFIG_CPU_SB1)
 
 /*
- * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
+ * Mostly like R4000 for historic reasons
  */
-
-__asm__(
-       "       .macro  irq_enable_hazard                       \n"
-       "       .endm                                           \n"
-       "                                                       \n"
-       "       .macro  irq_disable_hazard                      \n"
-       "       .endm                                           \n");
+ASMMACRO(mtc0_tlbw_hazard,
+       )
+ASMMACRO(tlbw_use_hazard,
+       )
+ASMMACRO(tlb_probe_hazard,
+       )
+ASMMACRO(irq_enable_hazard,
+       )
+ASMMACRO(irq_disable_hazard,
+        _ssnop; _ssnop; _ssnop
+       )
+ASMMACRO(back_to_back_c0_hazard,
+       )
+#define instruction_hazard() do { } while (0)
 
 #else
 
 /*
- * Default for classic MIPS processors.  Assume worst case hazards but don't
- * care about the irq_enable_hazard - sooner or later the hardware will
- * enable it and we don't care when exactly.
- */
-
-__asm__(
-       "       #                                               \n"
-       "       # There is a hazard but we do not care          \n"
-       "       #                                               \n"
-       "       .macro\tirq_enable_hazard                       \n"
-       "       .endm                                           \n"
-       "                                                       \n"
-       "       .macro\tirq_disable_hazard                      \n"
-       "       _ssnop                                          \n"
-       "       _ssnop                                          \n"
-       "       _ssnop                                          \n"
-       "       .endm                                           \n");
-
-#endif
-
-#define irq_enable_hazard()                                            \
-       __asm__ __volatile__("irq_enable_hazard")
-#define irq_disable_hazard()                                           \
-       __asm__ __volatile__("irq_disable_hazard")
-
-
-/*
- * Back-to-back hazards -
+ * Finally the catchall case for all other processors including R4000, R4400,
+ * R4600, R4700, R5000, RM7000, NEC VR41xx etc.
  *
- * What is needed to separate a move to cp0 from a subsequent read from the
- * same cp0 register?
- */
-#ifdef CONFIG_CPU_MIPSR2
-
-__asm__("      .macro  back_to_back_c0_hazard                  \n"
-       "       _ehb                                            \n"
-       "       .endm                                           \n");
-
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
-      defined(CONFIG_CPU_SB1)
-
-__asm__("      .macro  back_to_back_c0_hazard                  \n"
-       "       .endm                                           \n");
-
-#else
-
-__asm__("      .macro  back_to_back_c0_hazard                  \n"
-       "       .set    noreorder                               \n"
-       "       _ssnop                                          \n"
-       "       _ssnop                                          \n"
-       "       _ssnop                                          \n"
-       "       .set    reorder                                 \n"
-       "       .endm");
-
-#endif
-
-#define back_to_back_c0_hazard()                                       \
-       __asm__ __volatile__("back_to_back_c0_hazard")
-
-
-/*
- * Instruction execution hazard
- */
-#ifdef CONFIG_CPU_MIPSR2
-/*
- * gcc has a tradition of misscompiling the previous construct using the
- * address of a label as argument to inline assembler.  Gas otoh has the
- * annoying difference between la and dla which are only usable for 32-bit
- * rsp. 64-bit code, so can't be used without conditional compilation.
- * The alterantive is switching the assembler to 64-bit code which happens
- * to work right even for 32-bit code ...
+ * The taken branch will result in a two cycle penalty for the two killed
+ * instructions on R4000 / R4400.  Other processors only have a single cycle
+ * hazard so this is nice trick to have an optimal code for a range of
+ * processors.
  */
-#define instruction_hazard()                                           \
-do {                                                                   \
-       unsigned long tmp;                                              \
-                                                                       \
-       __asm__ __volatile__(                                           \
-       "       .set    mips64r2                                \n"     \
-       "       dla     %0, 1f                                  \n"     \
-       "       jr.hb   %0                                      \n"     \
-       "       .set    mips0                                   \n"     \
-       "1:                                                     \n"     \
-       : "=r" (tmp));                                                  \
-} while (0)
-
-#else
+ASMMACRO(mtc0_tlbw_hazard,
+       nop
+       )
+ASMMACRO(tlbw_use_hazard,
+       nop; nop; nop
+       )
+ASMMACRO(tlb_probe_hazard,
+        nop; nop; nop
+       )
+ASMMACRO(irq_enable_hazard,
+       )
+ASMMACRO(irq_disable_hazard,
+       nop; nop; nop
+       )
+ASMMACRO(back_to_back_c0_hazard,
+        _ssnop; _ssnop; _ssnop;
+       )
 #define instruction_hazard() do { } while (0)
-#endif
-
-extern void mips_ihb(void);
 
-#endif /* __ASSEMBLY__ */
+#endif
 
 #endif /* _ASM_HAZARDS_H */
index 896550bad3229cbd388fa8ce9705129ecdf91ca4..d35c61776a0249d5620a8a70a8033b15735f48fc 100644 (file)
@@ -76,8 +76,4 @@ extern int setup_irq_smtc(unsigned int irq, struct irqaction * new,
                           unsigned long hwmask);
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-#ifdef CONFIG_SMP
-#define ARCH_HAS_IRQ_PER_CPU
-#endif
-
 #endif /* _ASM_IRQ_H */
index 397522ea55650b0af3f1985105a3efc18296abf1..a73a5698420c1cde3486c42adbd4f5db6d349988 100644 (file)
 #include <asm/mips-boards/atlas.h>
 #include <asm/mips-boards/atlasint.h>
 
+#define ARCH_RTC_LOCATION
+
 #define RTC_PORT(x)    (ATLAS_RTC_ADR_REG + (x) * 8)
 #define RTC_IO_EXTENT  0x100
 #define RTC_IOMAPPED   0
-#define RTC_IRQ                ATLASINT_RTC
+#define RTC_IRQ                ATLAS_INT_RTC
 
 static inline unsigned char CMOS_READ(unsigned long addr)
 {
diff --git a/include/asm-mips/mach-ev96100/mach-gt64120.h b/include/asm-mips/mach-ev96100/mach-gt64120.h
deleted file mode 100644 (file)
index 0ef1e6c..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  This is a direct copy of the ev96100.h file, with a global
- * search and replace.  The numbers are the same.
- *
- *  The reason I'm duplicating this is so that the 64120/96100
- * defines won't be confusing in the source code.
- */
-#ifndef _ASM_GT64120_EV96100_GT64120_DEP_H
-#define _ASM_GT64120_EV96100_GT64120_DEP_H
-
-/*
- *   GT96100 config space base address
- */
-#define GT64120_BASE   (KSEG1ADDR(0x14000000))
-
-/*
- *   PCI Bus allocation
- *
- *   (Guessing ...)
- */
-#define GT_PCI_MEM_BASE        0x12000000UL
-#define GT_PCI_MEM_SIZE        0x02000000UL
-#define GT_PCI_IO_BASE 0x10000000UL
-#define GT_PCI_IO_SIZE 0x02000000UL
-#define GT_ISA_IO_BASE PCI_IO_BASE
-
-/*
- *   Duart I/O ports.
- */
-#define EV96100_COM1_BASE_ADDR (0xBD000000 + 0x20)
-#define EV96100_COM2_BASE_ADDR (0xBD000000 + 0x00)
-
-
-/*
- *   EV96100 interrupt controller register base.
- */
-#define EV96100_ICTRL_REGS_BASE        (KSEG1ADDR(0x1f000000))
-
-/*
- *   EV96100 UART register base.
- */
-#define EV96100_UART0_REGS_BASE        EV96100_COM1_BASE_ADDR
-#define EV96100_UART1_REGS_BASE        EV96100_COM2_BASE_ADDR
-#define EV96100_BASE_BAUD      ( 3686400 / 16 )
-
-#endif /* _ASM_GT64120_EV96100_GT64120_DEP_H */
index 130bd4b8edcea3210b703a9e441a09826ecb3587..4c29ba44992c11e8b1ffce23099b34dba6906512 100644 (file)
@@ -7,7 +7,7 @@
 
 #define EXCITE_CPU_EXT_CLOCK 100000000
 
-#if !defined(__ASSEMBLER__)
+#if !defined(__ASSEMBLY__)
 void __init excite_kgdb_init(void);
 void excite_procfs_init(void);
 extern unsigned long memsize;
index f4e370e271684e9fb8884a41c0c592c2e5cb9e4a..529445dacedb7283f44b3430ebdfb27602a76da2 100644 (file)
@@ -20,7 +20,7 @@
 
 #define cpu_has_llsc           1
 #define cpu_has_vtag_icache    0
-#define cpu_has_dc_aliases     (PAGE_SIZE < 0x4000)
+#define cpu_has_dc_aliases     0
 #define cpu_has_ic_fills_f_dc  0
 
 #define cpu_has_dsp            0
index fd7ebc54fa901ff7384df77024dca98abf6e257e..b15e4ea0b0911bdffa62b3c122663d9f8b8a5134 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999 MIPS Technologies, Inc.  All rights reserved.
+ * Copyright (C) 1999, 2006  MIPS Technologies, Inc.  All rights reserved.
+ *     Authors: Carsten Langgaard <carstenl@mips.com>
+ *              Maciej W. Rozycki <macro@mips.com>
  *
  * ########################################################################
  *
 #ifndef _MIPS_ATLASINT_H
 #define _MIPS_ATLASINT_H
 
-#define ATLASINT_BASE          1
-#define ATLASINT_UART          (ATLASINT_BASE+0)
-#define ATLASINT_TIM0          (ATLASINT_BASE+1)
-#define ATLASINT_RES2          (ATLASINT_BASE+2)
-#define ATLASINT_RES3          (ATLASINT_BASE+3)
-#define ATLASINT_RTC           (ATLASINT_BASE+4)
-#define ATLASINT_COREHI                (ATLASINT_BASE+5)
-#define ATLASINT_CORELO                (ATLASINT_BASE+6)
-#define ATLASINT_RES7          (ATLASINT_BASE+7)
-#define ATLASINT_PCIA          (ATLASINT_BASE+8)
-#define ATLASINT_PCIB          (ATLASINT_BASE+9)
-#define ATLASINT_PCIC          (ATLASINT_BASE+10)
-#define ATLASINT_PCID          (ATLASINT_BASE+11)
-#define ATLASINT_ENUM          (ATLASINT_BASE+12)
-#define ATLASINT_DEG           (ATLASINT_BASE+13)
-#define ATLASINT_ATXFAIL       (ATLASINT_BASE+14)
-#define ATLASINT_INTA          (ATLASINT_BASE+15)
-#define ATLASINT_INTB          (ATLASINT_BASE+16)
-#define ATLASINT_ETH           ATLASINT_INTB
-#define ATLASINT_INTC          (ATLASINT_BASE+17)
-#define ATLASINT_SCSI          ATLASINT_INTC
-#define ATLASINT_INTD          (ATLASINT_BASE+18)
-#define ATLASINT_SERR          (ATLASINT_BASE+19)
-#define ATLASINT_RES20         (ATLASINT_BASE+20)
-#define ATLASINT_RES21         (ATLASINT_BASE+21)
-#define ATLASINT_RES22         (ATLASINT_BASE+22)
-#define ATLASINT_RES23         (ATLASINT_BASE+23)
-#define ATLASINT_RES24         (ATLASINT_BASE+24)
-#define ATLASINT_RES25         (ATLASINT_BASE+25)
-#define ATLASINT_RES26         (ATLASINT_BASE+26)
-#define ATLASINT_RES27         (ATLASINT_BASE+27)
-#define ATLASINT_RES28         (ATLASINT_BASE+28)
-#define ATLASINT_RES29         (ATLASINT_BASE+29)
-#define ATLASINT_RES30         (ATLASINT_BASE+30)
-#define ATLASINT_RES31         (ATLASINT_BASE+31)
-#define ATLASINT_END           (ATLASINT_BASE+31)
+/*
+ * Interrupts 0..7 are used for Atlas CPU interrupts (nonEIC mode)
+ */
+#define MIPSCPU_INT_BASE       0
+
+/* CPU interrupt offsets */
+#define MIPSCPU_INT_SW0                0
+#define MIPSCPU_INT_SW1                1
+#define MIPSCPU_INT_MB0                2
+#define MIPSCPU_INT_ATLAS      MIPSCPU_INT_MB0
+#define MIPSCPU_INT_MB1                3
+#define MIPSCPU_INT_MB2                4
+#define MIPSCPU_INT_MB3                5
+#define MIPSCPU_INT_MB4                6
+#define MIPSCPU_INT_CPUCTR     7
+
+/*
+ * Interrupts 8..39 are used for Atlas interrupt controller interrupts
+ */
+#define ATLAS_INT_BASE         8
+#define ATLAS_INT_UART         (ATLAS_INT_BASE + 0)
+#define ATLAS_INT_TIM0         (ATLAS_INT_BASE + 1)
+#define ATLAS_INT_RES2         (ATLAS_INT_BASE + 2)
+#define ATLAS_INT_RES3         (ATLAS_INT_BASE + 3)
+#define ATLAS_INT_RTC          (ATLAS_INT_BASE + 4)
+#define ATLAS_INT_COREHI       (ATLAS_INT_BASE + 5)
+#define ATLAS_INT_CORELO       (ATLAS_INT_BASE + 6)
+#define ATLAS_INT_RES7         (ATLAS_INT_BASE + 7)
+#define ATLAS_INT_PCIA         (ATLAS_INT_BASE + 8)
+#define ATLAS_INT_PCIB         (ATLAS_INT_BASE + 9)
+#define ATLAS_INT_PCIC         (ATLAS_INT_BASE + 10)
+#define ATLAS_INT_PCID         (ATLAS_INT_BASE + 11)
+#define ATLAS_INT_ENUM         (ATLAS_INT_BASE + 12)
+#define ATLAS_INT_DEG          (ATLAS_INT_BASE + 13)
+#define ATLAS_INT_ATXFAIL      (ATLAS_INT_BASE + 14)
+#define ATLAS_INT_INTA         (ATLAS_INT_BASE + 15)
+#define ATLAS_INT_INTB         (ATLAS_INT_BASE + 16)
+#define ATLAS_INT_ETH          ATLAS_INT_INTB
+#define ATLAS_INT_INTC         (ATLAS_INT_BASE + 17)
+#define ATLAS_INT_SCSI         ATLAS_INT_INTC
+#define ATLAS_INT_INTD         (ATLAS_INT_BASE + 18)
+#define ATLAS_INT_SERR         (ATLAS_INT_BASE + 19)
+#define ATLAS_INT_RES20                (ATLAS_INT_BASE + 20)
+#define ATLAS_INT_RES21                (ATLAS_INT_BASE + 21)
+#define ATLAS_INT_RES22                (ATLAS_INT_BASE + 22)
+#define ATLAS_INT_RES23                (ATLAS_INT_BASE + 23)
+#define ATLAS_INT_RES24                (ATLAS_INT_BASE + 24)
+#define ATLAS_INT_RES25                (ATLAS_INT_BASE + 25)
+#define ATLAS_INT_RES26                (ATLAS_INT_BASE + 26)
+#define ATLAS_INT_RES27                (ATLAS_INT_BASE + 27)
+#define ATLAS_INT_RES28                (ATLAS_INT_BASE + 28)
+#define ATLAS_INT_RES29                (ATLAS_INT_BASE + 29)
+#define ATLAS_INT_RES30                (ATLAS_INT_BASE + 30)
+#define ATLAS_INT_RES31                (ATLAS_INT_BASE + 31)
+#define ATLAS_INT_END          (ATLAS_INT_BASE + 31)
+
+/*
+ * Interrupts 64..127 are used for Soc-it Classic interrupts
+ */
+#define MSC01C_INT_BASE                64
+
+/* SOC-it Classic interrupt offsets */
+#define MSC01C_INT_TMR         0
+#define MSC01C_INT_PCI         1
+
+/*
+ * Interrupts 64..127 are used for Soc-it EIC interrupts
+ */
+#define MSC01E_INT_BASE                64
+
+/* SOC-it EIC interrupt offsets */
+#define        MSC01E_INT_SW0          1
+#define        MSC01E_INT_SW1          2
+#define        MSC01E_INT_MB0          3
+#define        MSC01E_INT_ATLAS        MSC01E_INT_MB0
+#define        MSC01E_INT_MB1          4
+#define        MSC01E_INT_MB2          5
+#define        MSC01E_INT_MB3          6
+#define        MSC01E_INT_MB4          7
+#define        MSC01E_INT_TMR          8
+#define        MSC01E_INT_PCI          9
+#define        MSC01E_INT_PERFCTR      10
+#define        MSC01E_INT_CPUCTR       11
 
 #endif /* !(_MIPS_ATLASINT_H) */
index 18b69de87daa14ff4881a5bc10ffd3c999e0be5a..fe065d6070ca3885b4f4f3f9467a87de01fed0e8 100644 (file)
@@ -262,10 +262,10 @@ drop_mmu_context(struct mm_struct *mm, unsigned cpu)
                /* See comments for similar code above */
                prevvpe = dvpe();
                oldasid = (read_c0_entryhi() & ASID_MASK);
-               if(smtc_live_asid[mytlb][oldasid]) {
-                 smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
-                 if(smtc_live_asid[mytlb][oldasid] == 0)
-                       smtc_flush_tlb_asid(oldasid);
+               if (smtc_live_asid[mytlb][oldasid]) {
+                       smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+                       if(smtc_live_asid[mytlb][oldasid] == 0)
+                               smtc_flush_tlb_asid(oldasid);
                }
                /* See comments for similar code above */
                write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
index 219d359861f3df8a522914aec8b71b6a88cf5e66..85b258ee7090737d4864ae068f00833bb8e59f53 100644 (file)
@@ -34,6 +34,8 @@
 
 #ifndef __ASSEMBLY__
 
+#include <asm/cpu-features.h>
+
 extern void clear_page(void * page);
 extern void copy_page(void * to, void * from);
 
@@ -53,7 +55,7 @@ static inline void clear_user_page(void *addr, unsigned long vaddr,
        extern void (*flush_data_cache_page)(unsigned long addr);
 
        clear_page(addr);
-       if (pages_do_alias((unsigned long) addr, vaddr))
+       if (pages_do_alias((unsigned long) addr, vaddr & PAGE_MASK))
                flush_data_cache_page((unsigned long)addr);
 }
 
@@ -63,7 +65,8 @@ static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
        extern void (*flush_data_cache_page)(unsigned long addr);
 
        copy_page(vto, vfrom);
-       if (pages_do_alias((unsigned long)vto, vaddr))
+       if (!cpu_has_ic_fills_f_dc ||
+           pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
                flush_data_cache_page((unsigned long)vto);
 }
 
@@ -74,15 +77,17 @@ static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
   #ifdef CONFIG_CPU_MIPS32
     typedef struct { unsigned long pte_low, pte_high; } pte_t;
     #define pte_val(x)    ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
+    #define __pte(x)      ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; })
   #else
      typedef struct { unsigned long long pte; } pte_t;
      #define pte_val(x)        ((x).pte)
+     #define __pte(x)  ((pte_t) { (x) } )
   #endif
 #else
 typedef struct { unsigned long pte; } pte_t;
 #define pte_val(x)     ((x).pte)
-#endif
 #define __pte(x)       ((pte_t) { (x) } )
+#endif
 
 /*
  * For 3-level pagetables we defines these ourselves, for 2-level the
index c59a1e21f5b0d26c87c2606a3a64fa74e84487a8..d05fb6f38aa7523c61e943f81d33ab2257058a1d 100644 (file)
 #define PTRS_PER_PMD   ((PAGE_SIZE << PMD_ORDER) / sizeof(pmd_t))
 #define PTRS_PER_PTE   ((PAGE_SIZE << PTE_ORDER) / sizeof(pte_t))
 
+#if PGDIR_SIZE >= TASK_SIZE
+#define USER_PTRS_PER_PGD       (1)
+#else
 #define USER_PTRS_PER_PGD      (TASK_SIZE / PGDIR_SIZE)
-#define FIRST_USER_ADDRESS     0
+#endif
+#define FIRST_USER_ADDRESS     0UL
 
 #define VMALLOC_START          MAP_BASE
 #define VMALLOC_END    \
index 4113316ee0da595bc6292bb50bbedb19737dcb46..4fb0fc43ffd71af828d8362052612b32b7fcafc1 100644 (file)
@@ -10,8 +10,6 @@
 #define _ASM_PTRACE_H
 
 
-#include <asm/isadep.h>
-
 /* 0 - 31 are integer registers, 32 - 63 are fp registers.  */
 #define FPR_BASE       32
 #define PC             64
@@ -73,6 +71,7 @@ struct pt_regs {
 #ifdef __KERNEL__
 
 #include <linux/linkage.h>
+#include <asm/isadep.h>
 
 /*
  * Does the process account for user or for system time?
index 584bd9c0ab2e862f8267ea78af7c5ede2700acd4..035637c67e7c0ab2c29b62f5d16dc7ce85b42c62 100644 (file)
@@ -52,9 +52,9 @@
 #endif
 
 /*
- * Both Galileo boards have the same UART mappings.
+ * Galileo EV64120 evaluation board
  */
-#if defined (CONFIG_MIPS_EV96100) || defined (CONFIG_MIPS_EV64120)
+#ifdef CONFIG_MIPS_EV64120
 #include <asm/galileo-boards/ev96100.h>
 #include <asm/galileo-boards/ev96100int.h>
 #define EV96100_SERIAL_PORT_DEFNS                                  \
index 335dbaf1d8319a1e1d2c352b12fa75e68e6652ce..a885491217c18da6d6515563e783dce1c11d881a 100644 (file)
  * Note: you'll need to define uint32_t and uint64_t in your headers.
  */
 
-#if !defined(__ASSEMBLER__)
+#if !defined(__ASSEMBLY__)
 #define _SB_MAKE64(x) ((uint64_t)(x))
 #define _SB_MAKE32(x) ((uint32_t)(x))
 #else
  */
 
 
-#if defined(__mips64) && !defined(__ASSEMBLER__)
+#if defined(__mips64) && !defined(__ASSEMBLY__)
 #define SBWRITECSR(csr,val) *((volatile uint64_t *) PHYS_TO_K1(csr)) = (val)
 #define SBREADCSR(csr) (*((volatile uint64_t *) PHYS_TO_K1(csr)))
-#endif /* __ASSEMBLER__ */
+#endif /* __ASSEMBLY__ */
 
 #endif
index f4178bdcfcb08636ec4985a8e52de6d784ae7372..7ed0bb611e56131035cad690422cd49fdbeed224 100644 (file)
  * (For the assembler version, sysrev and dest may be the same register.
  * Also, it clobbers AT.)
  */
-#ifdef __ASSEMBLER__
+#ifdef __ASSEMBLY__
 #define SYS_SOC_TYPE(dest, sysrev)                                     \
        .set push ;                                                     \
        .set reorder ;                                                  \
index 87a1dff9519917d2480025310e54dc6a5dfd9830..8b391a2f0814ad113d4313be9bd84dd351d4a541 100644 (file)
@@ -108,17 +108,8 @@ typedef unsigned long old_sigset_t;                /* at least 32 bits */
 #define SIG_BLOCK      1       /* for blocking signals */
 #define SIG_UNBLOCK    2       /* for unblocking signals */
 #define SIG_SETMASK    3       /* for setting the signal mask */
-#define SIG_SETMASK32  256     /* Goodie from SGI for BSD compatibility:
-                                  set only the low 32 bit of the sigset.  */
 
-/* Type of a signal handler.  */
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
-
-/* Fake signal functions */
-#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
-#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
-#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
+#include <asm-generic/signal.h>
 
 struct sigaction {
        unsigned int    sa_flags;
index 669b8e349ff29544fce6a35c91307950ba660f4a..4c1a1b53aeaf1c3db24c8f01fab27147600e0020 100644 (file)
@@ -239,7 +239,51 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw)
        : "memory");
 }
 
-#define __raw_read_trylock(lock) generic__raw_read_trylock(lock)
+static inline int __raw_read_trylock(raw_rwlock_t *rw)
+{
+       unsigned int tmp;
+       int ret;
+
+       if (R10000_LLSC_WAR) {
+               __asm__ __volatile__(
+               "       .set    noreorder       # __raw_read_trylock    \n"
+               "       li      %2, 0                                   \n"
+               "1:     ll      %1, %3                                  \n"
+               "       bnez    %1, 2f                                  \n"
+               "        addu   %1, 1                                   \n"
+               "       sc      %1, %0                                  \n"
+               "       beqzl   %1, 1b                                  \n"
+               "       .set    reorder                                 \n"
+#ifdef CONFIG_SMP
+               "        sync                                           \n"
+#endif
+               "       li      %2, 1                                   \n"
+               "2:                                                     \n"
+               : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
+               : "m" (rw->lock)
+               : "memory");
+       } else {
+               __asm__ __volatile__(
+               "       .set    noreorder       # __raw_read_trylock    \n"
+               "       li      %2, 0                                   \n"
+               "1:     ll      %1, %3                                  \n"
+               "       bnez    %1, 2f                                  \n"
+               "        addu   %1, 1                                   \n"
+               "       sc      %1, %0                                  \n"
+               "       beqz    %1, 1b                                  \n"
+               "       .set    reorder                                 \n"
+#ifdef CONFIG_SMP
+               "        sync                                           \n"
+#endif
+               "       li      %2, 1                                   \n"
+               "2:                                                     \n"
+               : "=m" (rw->lock), "=&r" (tmp), "=&r" (ret)
+               : "m" (rw->lock)
+               : "memory");
+       }
+
+       return ret;
+}
 
 static inline int __raw_write_trylock(raw_rwlock_t *rw)
 {
@@ -283,4 +327,5 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)
        return ret;
 }
 
+
 #endif /* _ASM_SPINLOCK_H */
index 98aa737b34aa75fc79d582431fcd12bf2bc42a43..b80de8e0fbbda8d8ca9f66dad92c32e25ce6e05a 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _ASM_TIMEX_H
 #define _ASM_TIMEX_H
 
+#ifdef __KERNEL__
+
 #include <asm/mipsregs.h>
 
 /*
@@ -51,4 +53,6 @@ static inline cycles_t get_cycles (void)
        return read_c0_count();
 }
 
+#endif /* __KERNEL__ */
+
 #endif /*  _ASM_TIMEX_H */
index 610ccb8a50b3a6fc1fe427de0c50be79edae646b..c39142920fe6e61bd2610345fd8849a051c54676 100644 (file)
 #define __NR_mknodat                   (__NR_Linux + 290)
 #define __NR_fchownat                  (__NR_Linux + 291)
 #define __NR_futimesat                 (__NR_Linux + 292)
-#define __NR_fstatat                   (__NR_Linux + 293)
+#define __NR_fstatat64                 (__NR_Linux + 293)
 #define __NR_unlinkat                  (__NR_Linux + 294)
 #define __NR_renameat                  (__NR_Linux + 295)
 #define __NR_linkat                    (__NR_Linux + 296)
 #define __NR_tee                       (__NR_Linux + 306)
 #define __NR_vmsplice                  (__NR_Linux + 307)
 #define __NR_move_pages                        (__NR_Linux + 308)
+#define __NR_set_robust_list           (__NR_Linux + 309)
+#define __NR_get_robust_list           (__NR_Linux + 310)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            308
+#define __NR_Linux_syscalls            310
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                308
+#define __NR_O32_Linux_syscalls                310
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_mknodat                   (__NR_Linux + 249)
 #define __NR_fchownat                  (__NR_Linux + 250)
 #define __NR_futimesat                 (__NR_Linux + 251)
-#define __NR_fstatat                   (__NR_Linux + 252)
+#define __NR_newfstatat                        (__NR_Linux + 252)
 #define __NR_unlinkat                  (__NR_Linux + 253)
 #define __NR_renameat                  (__NR_Linux + 254)
 #define __NR_linkat                    (__NR_Linux + 255)
 #define __NR_tee                       (__NR_Linux + 265)
 #define __NR_vmsplice                  (__NR_Linux + 266)
 #define __NR_move_pages                        (__NR_Linux + 267)
+#define __NR_set_robust_list           (__NR_Linux + 268)
+#define __NR_get_robust_list           (__NR_Linux + 269)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            267
+#define __NR_Linux_syscalls            269
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         267
+#define __NR_64_Linux_syscalls         269
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_mknodat                   (__NR_Linux + 253)
 #define __NR_fchownat                  (__NR_Linux + 254)
 #define __NR_futimesat                 (__NR_Linux + 255)
-#define __NR_fstatat                   (__NR_Linux + 256)
+#define __NR_newfstatat                        (__NR_Linux + 256)
 #define __NR_unlinkat                  (__NR_Linux + 257)
 #define __NR_renameat                  (__NR_Linux + 258)
 #define __NR_linkat                    (__NR_Linux + 259)
 #define __NR_tee                       (__NR_Linux + 269)
 #define __NR_vmsplice                  (__NR_Linux + 270)
 #define __NR_move_pages                        (__NR_Linux + 271)
+#define __NR_set_robust_list           (__NR_Linux + 272)
+#define __NR_get_robust_list           (__NR_Linux + 273)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            271
+#define __NR_Linux_syscalls            273
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                271
+#define __NR_N32_Linux_syscalls                273
 
 #ifdef __KERNEL__
 
index 89bf8b4cab3c333b07c0388f546dc2bc1ed1286a..61f2a093b91befa8476bbafd52cb291d5588db45 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _ASM_USER_H
 #define _ASM_USER_H
 
+#ifdef __KERNEL__
+
 #include <asm/page.h>
 #include <asm/reg.h>
 
@@ -55,4 +57,6 @@ struct user {
 #define HOST_DATA_START_ADDR   (u.start_data)
 #define HOST_STACK_END_ADDR    (u.start_stack + u.u_ssize * NBPG)
 
+#endif /* __KERNEL__ */
+
 #endif /* _ASM_USER_H */
index 02b942d85c377369abea006db9d932bef89b1cce..d49c54cb5505a03d8ee8920af9e2d08f662bbffd 100644 (file)
 
 #ifdef __KERNEL__
 
+#include <linux/err.h>
+
 #define __syscall_return(type, res)                         \
 do {                                                        \
-       if ((unsigned long)(res) >= (unsigned long)(-4095)) {\
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
                errno = -(res);                              \
                res = -1;                                    \
        }                                                    \
index 720afc11c2caf7c4e95d7943894337ef25ec154d..b860218e402e88622a311a6036424f1ba3e6aa19 100644 (file)
 #include <asm/cpu/addrspace.h>
 
 /* Memory segments (32bit Privileged mode addresses)  */
+#ifndef CONFIG_CPU_SH2A
 #define P0SEG          0x00000000
 #define P1SEG          0x80000000
 #define P2SEG          0xa0000000
 #define P3SEG          0xc0000000
 #define P4SEG          0xe0000000
+#else
+#define P0SEG          0x00000000
+#define P1SEG          0x00000000
+#define P2SEG          0x20000000
+#define P3SEG          0x00000000
+#define P4SEG          0x80000000
+#endif
 
 /* Returns the privileged segment base of a given address  */
 #define PXSEG(a)       (((unsigned long)(a)) & 0xe0000000)
diff --git a/include/asm-sh/adx/io.h b/include/asm-sh/adx/io.h
deleted file mode 100644 (file)
index ab1225f..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * include/asm-sh/io_adx.h
- *
- * Copyright (C) 2001 A&D Co., Ltd.
- *
- * This file may be copied or modified under the terms of the GNU
- * General Public License.  See linux/COPYING for more information.
- *
- * IO functions for an A&D ADX Board
- */
-
-#ifndef _ASM_SH_IO_ADX_H
-#define _ASM_SH_IO_ADX_H
-
-#include <asm/io_generic.h>
-
-extern unsigned char adx_inb(unsigned long port);
-extern unsigned short adx_inw(unsigned long port);
-extern unsigned int adx_inl(unsigned long port);
-
-extern void adx_outb(unsigned char value, unsigned long port);
-extern void adx_outw(unsigned short value, unsigned long port);
-extern void adx_outl(unsigned int value, unsigned long port);
-
-extern unsigned char adx_inb_p(unsigned long port);
-extern void adx_outb_p(unsigned char value, unsigned long port);
-
-extern void adx_insb(unsigned long port, void *addr, unsigned long count);
-extern void adx_insw(unsigned long port, void *addr, unsigned long count);
-extern void adx_insl(unsigned long port, void *addr, unsigned long count);
-extern void adx_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void adx_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void adx_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned char adx_readb(unsigned long addr);
-extern unsigned short adx_readw(unsigned long addr);
-extern unsigned int adx_readl(unsigned long addr);
-extern void adx_writeb(unsigned char b, unsigned long addr);
-extern void adx_writew(unsigned short b, unsigned long addr);
-extern void adx_writel(unsigned int b, unsigned long addr);
-
-extern void * adx_ioremap(unsigned long offset, unsigned long size);
-extern void adx_iounmap(void *addr);
-
-extern unsigned long adx_isa_port2addr(unsigned long offset);
-
-extern void setup_adx(void);
-extern void init_adx_IRQ(void);
-
-#ifdef __WANT_IO_DEF
-
-#define __inb          adx_inb
-#define __inw          adx_inw
-#define __inl          adx_inl
-#define __outb         adx_outb
-#define __outw         adx_outw
-#define __outl         adx_outl
-
-#define __inb_p                adx_inb_p
-#define __inw_p                adx_inw
-#define __inl_p                adx_inl
-#define __outb_p       adx_outb_p
-#define __outw_p       adx_outw
-#define __outl_p       adx_outl
-
-#define __insb         adx_insb
-#define __insw         adx_insw
-#define __insl         adx_insl
-#define __outsb                adx_outsb
-#define __outsw                adx_outsw
-#define __outsl                adx_outsl
-
-#define __readb                adx_readb
-#define __readw                adx_readw
-#define __readl                adx_readl
-#define __writeb       adx_writeb
-#define __writew       adx_writew
-#define __writel       adx_writel
-
-#define __isa_port2addr        adx_isa_port2addr
-#define __ioremap      adx_ioremap
-#define __iounmap      adx_iounmap
-
-#endif
-
-#endif /* _ASM_SH_IO_AANDD_H */
diff --git a/include/asm-sh/apm.h b/include/asm-sh/apm.h
new file mode 100644 (file)
index 0000000..8b091e9
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2006 (c) Andriy Skulysh <askulysh@gmail.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#ifndef __ASM_SH_APM_H
+#define __ASM_SH_APM_H
+
+#define APM_AC_OFFLINE                 0
+#define APM_AC_ONLINE                  1
+#define APM_AC_BACKUP                  2
+#define APM_AC_UNKNOWN                 0xff
+
+#define APM_BATTERY_STATUS_HIGH                0
+#define APM_BATTERY_STATUS_LOW         1
+#define APM_BATTERY_STATUS_CRITICAL    2
+#define APM_BATTERY_STATUS_CHARGING    3
+#define APM_BATTERY_STATUS_NOT_PRESENT 4
+#define APM_BATTERY_STATUS_UNKNOWN     0xff
+
+#define APM_BATTERY_LIFE_UNKNOWN       0xFFFF
+#define APM_BATTERY_LIFE_MINUTES       0x8000
+#define APM_BATTERY_LIFE_VALUE_MASK    0x7FFF
+
+#define APM_BATTERY_FLAG_HIGH          (1 << 0)
+#define APM_BATTERY_FLAG_LOW           (1 << 1)
+#define APM_BATTERY_FLAG_CRITICAL      (1 << 2)
+#define APM_BATTERY_FLAG_CHARGING      (1 << 3)
+#define APM_BATTERY_FLAG_NOT_PRESENT   (1 << 7)
+#define APM_BATTERY_FLAG_UNKNOWN       0xff
+
+#define APM_UNITS_MINS                 0
+#define APM_UNITS_SECS                 1
+#define APM_UNITS_UNKNOWN              -1
+
+
+extern int (*apm_get_info)(char *buf, char **start, off_t fpos, int length);
+extern int apm_suspended;
+
+void apm_queue_event(apm_event_t event);
+
+#endif
index fb627de217f2e3bd9668e9de53c48139527113d9..8bdc1ba56f736570788c445bf5ef4f4dc1bde5a8 100644 (file)
@@ -14,6 +14,7 @@ typedef struct { volatile int counter; } atomic_t;
 #define atomic_read(v)         ((v)->counter)
 #define atomic_set(v,i)                ((v)->counter = (i))
 
+#include <linux/compiler.h>
 #include <asm/system.h>
 
 /*
@@ -21,49 +22,110 @@ typedef struct { volatile int counter; } atomic_t;
  * forward to code at the end of this object's .text section, then
  * branch back to restart the operation.
  */
-
-static __inline__ void atomic_add(int i, atomic_t * v)
+static inline void atomic_add(int i, atomic_t *v)
 {
+#ifdef CONFIG_CPU_SH4A
+       unsigned long tmp;
+
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_add    \n"
+"      add     %2, %0                          \n"
+"      movco.l %0, @%3                         \n"
+"      bf      1b                              \n"
+       : "=&z" (tmp), "=r" (&v->counter)
+       : "r" (i), "r" (&v->counter)
+       : "t");
+#else
        unsigned long flags;
 
        local_irq_save(flags);
        *(long *)v += i;
        local_irq_restore(flags);
+#endif
 }
 
-static __inline__ void atomic_sub(int i, atomic_t *v)
+static inline void atomic_sub(int i, atomic_t *v)
 {
+#ifdef CONFIG_CPU_SH4A
+       unsigned long tmp;
+
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_sub    \n"
+"      sub     %2, %0                          \n"
+"      movco.l %0, @%3                         \n"
+"      bf      1b                              \n"
+       : "=&z" (tmp), "=r" (&v->counter)
+       : "r" (i), "r" (&v->counter)
+       : "t");
+#else
        unsigned long flags;
 
        local_irq_save(flags);
        *(long *)v -= i;
        local_irq_restore(flags);
+#endif
 }
 
-static __inline__ int atomic_add_return(int i, atomic_t * v)
+/*
+ * SH-4A note:
+ *
+ * We basically get atomic_xxx_return() for free compared with
+ * atomic_xxx(). movli.l/movco.l require r0 due to the instruction
+ * encoding, so the retval is automatically set without having to
+ * do any special work.
+ */
+static inline int atomic_add_return(int i, atomic_t *v)
 {
-       unsigned long temp, flags;
+       unsigned long temp;
+
+#ifdef CONFIG_CPU_SH4A
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_add_return     \n"
+"      add     %2, %0                                  \n"
+"      movco.l %0, @%3                                 \n"
+"      bf      1b                                      \n"
+"      synco                                           \n"
+       : "=&z" (temp), "=r" (&v->counter)
+       : "r" (i), "r" (&v->counter)
+       : "t");
+#else
+       unsigned long flags;
 
        local_irq_save(flags);
        temp = *(long *)v;
        temp += i;
        *(long *)v = temp;
        local_irq_restore(flags);
+#endif
 
        return temp;
 }
 
 #define atomic_add_negative(a, v)      (atomic_add_return((a), (v)) < 0)
 
-static __inline__ int atomic_sub_return(int i, atomic_t * v)
+static inline int atomic_sub_return(int i, atomic_t *v)
 {
-       unsigned long temp, flags;
+       unsigned long temp;
+
+#ifdef CONFIG_CPU_SH4A
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_sub_return     \n"
+"      sub     %2, %0                                  \n"
+"      movco.l %0, @%3                                 \n"
+"      bf      1b                                      \n"
+"      synco                                           \n"
+       : "=&z" (temp), "=r" (&v->counter)
+       : "r" (i), "r" (&v->counter)
+       : "t");
+#else
+       unsigned long flags;
 
        local_irq_save(flags);
        temp = *(long *)v;
        temp -= i;
        *(long *)v = temp;
        local_irq_restore(flags);
+#endif
 
        return temp;
 }
@@ -118,22 +180,48 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
 }
 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 
-static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v)
+static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
 {
+#ifdef CONFIG_CPU_SH4A
+       unsigned long tmp;
+
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_clear_mask     \n"
+"      and     %2, %0                                  \n"
+"      movco.l %0, @%3                                 \n"
+"      bf      1b                                      \n"
+       : "=&z" (tmp), "=r" (&v->counter)
+       : "r" (~mask), "r" (&v->counter)
+       : "t");
+#else
        unsigned long flags;
 
        local_irq_save(flags);
        *(long *)v &= ~mask;
        local_irq_restore(flags);
+#endif
 }
 
-static __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
+static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
 {
+#ifdef CONFIG_CPU_SH4A
+       unsigned long tmp;
+
+       __asm__ __volatile__ (
+"1:    movli.l @%3, %0         ! atomic_set_mask       \n"
+"      or      %2, %0                                  \n"
+"      movco.l %0, @%3                                 \n"
+"      bf      1b                                      \n"
+       : "=&z" (tmp), "=r" (&v->counter)
+       : "r" (mask), "r" (&v->counter)
+       : "t");
+#else
        unsigned long flags;
 
        local_irq_save(flags);
        *(long *)v |= mask;
        local_irq_restore(flags);
+#endif
 }
 
 /* Atomic operations are already serializing on SH */
index fc21e4db588142a606e7130d3bc5caaa7c4e9155..1b6916e63e90884fd7b058510903a28379462aba 100644 (file)
@@ -1,4 +1,18 @@
 #ifndef __ASM_SH_AUXVEC_H
 #define __ASM_SH_AUXVEC_H
 
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them.
+ */
+
+#ifdef CONFIG_VSYSCALL
+/*
+ * Only define this in the vsyscall case, the entry point to
+ * the vsyscall page gets placed here. The kernel will attempt
+ * to build a gate VMA we don't care about otherwise..
+ */
+#define AT_SYSINFO_EHDR                33
+#endif
+
 #endif /* __ASM_SH_AUXVEC_H */
index e34f8250856897b7ee4c5f960cf444fd03f21646..1c16792cee1dbaf239948ac8971dd2ad7290865e 100644 (file)
@@ -6,7 +6,7 @@
 /* For __swab32 */
 #include <asm/byteorder.h>
 
-static __inline__ void set_bit(int nr, volatile void * addr)
+static inline void set_bit(int nr, volatile void * addr)
 {
        int     mask;
        volatile unsigned int *a = addr;
@@ -24,7 +24,7 @@ static __inline__ void set_bit(int nr, volatile void * addr)
  */
 #define smp_mb__before_clear_bit()     barrier()
 #define smp_mb__after_clear_bit()      barrier()
-static __inline__ void clear_bit(int nr, volatile void * addr)
+static inline void clear_bit(int nr, volatile void * addr)
 {
        int     mask;
        volatile unsigned int *a = addr;
@@ -37,7 +37,7 @@ static __inline__ void clear_bit(int nr, volatile void * addr)
        local_irq_restore(flags);
 }
 
-static __inline__ void change_bit(int nr, volatile void * addr)
+static inline void change_bit(int nr, volatile void * addr)
 {
        int     mask;
        volatile unsigned int *a = addr;
@@ -50,7 +50,7 @@ static __inline__ void change_bit(int nr, volatile void * addr)
        local_irq_restore(flags);
 }
 
-static __inline__ int test_and_set_bit(int nr, volatile void * addr)
+static inline int test_and_set_bit(int nr, volatile void * addr)
 {
        int     mask, retval;
        volatile unsigned int *a = addr;
@@ -66,7 +66,7 @@ static __inline__ int test_and_set_bit(int nr, volatile void * addr)
        return retval;
 }
 
-static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+static inline int test_and_clear_bit(int nr, volatile void * addr)
 {
        int     mask, retval;
        volatile unsigned int *a = addr;
@@ -82,7 +82,7 @@ static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
        return retval;
 }
 
-static __inline__ int test_and_change_bit(int nr, volatile void * addr)
+static inline int test_and_change_bit(int nr, volatile void * addr)
 {
        int     mask, retval;
        volatile unsigned int *a = addr;
@@ -100,7 +100,7 @@ static __inline__ int test_and_change_bit(int nr, volatile void * addr)
 
 #include <asm-generic/bitops/non-atomic.h>
 
-static __inline__ unsigned long ffz(unsigned long word)
+static inline unsigned long ffz(unsigned long word)
 {
        unsigned long result;
 
@@ -120,7 +120,7 @@ static __inline__ unsigned long ffz(unsigned long word)
  *
  * Undefined if no bit exists, so code should check against 0 first.
  */
-static __inline__ unsigned long __ffs(unsigned long word)
+static inline unsigned long __ffs(unsigned long word)
 {
        unsigned long result;
 
index a6de3d06a3d9832a40db41ad704188e45be3b20b..b4000c8bf31b8b76161b93c227a9bfa24c8ad0a3 100644 (file)
@@ -32,6 +32,10 @@ static void __init check_bugs(void)
        case CPU_SH7750 ... CPU_SH4_501:
                *p++ = '4';
                break;
+       case CPU_SH7770 ... CPU_SH7781:
+               *p++ = '4';
+               *p++ = 'a';
+               break;
        default:
                *p++ = '?';
                *p++ = '!';
index 656fdfe9e8b445ee16e6f833e62f7e10bc783a20..e3a180cf506285dbffe07273c60bc35837f54ce9 100644 (file)
@@ -10,7 +10,6 @@
 #ifdef __KERNEL__
 
 #include <asm/cpu/cache.h>
-#include <asm/cpu/cacheflush.h>
 
 #define SH_CACHE_VALID         1
 #define SH_CACHE_UPDATED       2
 #define L1_CACHE_ALIGN(x)      (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 
 struct cache_info {
-       unsigned int ways;
-       unsigned int sets;
-       unsigned int linesz;
+       unsigned int ways;              /* Number of cache ways */
+       unsigned int sets;              /* Number of cache sets */
+       unsigned int linesz;            /* Cache line size (bytes) */
 
-       unsigned int way_incr;
+       unsigned int way_size;          /* sets * line size */
 
+       /*
+        * way_incr is the address offset for accessing the next way
+        * in memory mapped cache array ops.
+        */
+       unsigned int way_incr;
        unsigned int entry_shift;
        unsigned int entry_mask;
 
+       /*
+        * Compute a mask which selects the address bits which overlap between
+        * 1. those used to select the cache set during indexing
+        * 2. those in the physical page number.
+        */
+       unsigned int alias_mask;
+
+       unsigned int n_aliases;         /* Number of aliases */
+
        unsigned long flags;
 };
 
-/* Flush (write-back only) a region (smaller than a page) */
-extern void __flush_wback_region(void *start, int size);
-/* Flush (write-back & invalidate) a region (smaller than a page) */
-extern void __flush_purge_region(void *start, int size);
-/* Flush (invalidate only) a region (smaller than a page) */
-extern void __flush_invalidate_region(void *start, int size);
-
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHE_H */
index 9dfb33edb00813368fdbfd87758358aed60a767c..07f62ec9ff0c8b9309d223f0424b0926afb86f4b 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_SH_CACHEFLUSH_H
 #ifdef __KERNEL__
 
+#include <linux/mm.h>
 #include <asm/cpu/cacheflush.h>
 
 /* Flush (write-back only) a region (smaller than a page) */
@@ -27,5 +28,7 @@ extern void __flush_invalidate_region(void *start, int size);
                memcpy(dst, src, len);                          \
        } while (0)
 
+#define HAVE_ARCH_UNMAPPED_AREA
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHEFLUSH_H */
diff --git a/include/asm-sh/cat68701/io.h b/include/asm-sh/cat68701/io.h
deleted file mode 100644 (file)
index 753b846..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * include/asm-sh/io_cat68701.h
- *
- * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
- *           2001 Yutarou Ebihar (ebihara@si-linux.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for an AONE Corp. CAT-68701 SH7708 Borad
- */
-
-#ifndef _ASM_SH_IO_CAT68701_H
-#define _ASM_SH_IO_CAT68701_H
-
-extern unsigned long cat68701_isa_port2addr(unsigned long offset);
-extern int cat68701_irq_demux(int irq);
-
-extern void init_cat68701_IRQ(void);
-extern void heartbeat_cat68701(void);
-
-#endif /* _ASM_SH_IO_CAT68701_H */
index fa03b30c4269f6ee60080ba2982c4c986ca8417a..08168afe6746a3d43a6e93da269566dad4c8bcc3 100644 (file)
@@ -159,6 +159,7 @@ static __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
 }
 
 #define _HAVE_ARCH_IPV6_CSUM
+#ifdef CONFIG_IPV6
 static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
                                                     struct in6_addr *daddr,
                                                     __u32 len,
@@ -194,6 +195,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
 
        return csum_fold(sum);
 }
+#endif
 
 /* 
  *     Copy and checksum to user
diff --git a/include/asm-sh/cpu-features.h b/include/asm-sh/cpu-features.h
new file mode 100644 (file)
index 0000000..4bccd7c
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __ASM_SH_CPU_FEATURES_H
+#define __ASM_SH_CPU_FEATURES_H
+
+/*
+ * Processor flags
+ *
+ * Note: When adding a new flag, keep cpu_flags[] in
+ * arch/sh/kernel/setup.c in sync so symbolic name
+ * mapping of the processor flags has a chance of being
+ * reasonably accurate.
+ *
+ * These flags are also available through the ELF
+ * auxiliary vector as AT_HWCAP.
+ */
+#define CPU_HAS_FPU            0x0001  /* Hardware FPU support */
+#define CPU_HAS_P2_FLUSH_BUG   0x0002  /* Need to flush the cache in P2 area */
+#define CPU_HAS_MMU_PAGE_ASSOC 0x0004  /* SH3: TLB way selection bit support */
+#define CPU_HAS_DSP            0x0008  /* SH-DSP: DSP support */
+#define CPU_HAS_PERF_COUNTER   0x0010  /* Hardware performance counters */
+#define CPU_HAS_PTEA           0x0020  /* PTEA register */
+#define CPU_HAS_LLSC           0x0040  /* movli.l/movco.l */
+#define CPU_HAS_L2_CACHE       0x0080  /* Secondary cache / URAM */
+
+#endif /* __ASM_SH_CPU_FEATURES_H */
diff --git a/include/asm-sh/cpu-sh2/shmparam.h b/include/asm-sh/cpu-sh2/shmparam.h
deleted file mode 100644 (file)
index 817c182..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-sh/cpu-sh2/shmparam.h
- *
- * Copyright (C) 2003  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.
- */
-#ifndef __ASM_CPU_SH2_SHMPARAM_H
-#define __ASM_CPU_SH2_SHMPARAM_H
-
-#define        SHMLBA PAGE_SIZE                 /* attach addr a multiple of this */
-
-#endif /* __ASM_CPU_SH2_SHMPARAM_H */
-
index 406aa8d9b9476ceb93edb0a58d2fbc31b084b3d6..ffe08d2813f996152b5cdba1fb626372ecbcabdb 100644 (file)
 #define CCR_CACHE_ENABLE       CCR_CACHE_CE
 #define CCR_CACHE_INVALIDATE   CCR_CACHE_CF
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7705)
+#if defined(CONFIG_CPU_SUBTYPE_SH7705) || defined(CONFIG_CPU_SUBTYPE_SH7710)
 #define CCR3   0xa40000b4
 #define CCR_CACHE_16KB  0x00010000
 #define CCR_CACHE_32KB 0x00020000
 #endif
 
-
 #endif /* __ASM_CPU_SH3_CACHE_H */
-
index f51aed00c68f762132c14e9173f4579c6fac6171..03fde97a7fd0eaf9d5ba8f6237f0b3aa5d76958e 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef __ASM_CPU_SH3_CACHEFLUSH_H
 #define __ASM_CPU_SH3_CACHEFLUSH_H
 
-/* 
+/*
  * Cache flushing:
  *
  *  - flush_cache_all() flushes entire cache
  /* 32KB cache, 4kb PAGE sizes need to check bit 12 */
 #define CACHE_ALIAS 0x00001000
 
-struct page;
-struct mm_struct;
-struct vm_area_struct;
-
-extern void flush_cache_all(void);
-extern void flush_cache_mm(struct mm_struct *mm);
-extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-                              unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
-extern void flush_dcache_page(struct page *pg);
-extern void flush_icache_range(unsigned long start, unsigned long end);
-extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
-
-#define flush_dcache_mmap_lock(mapping)                do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
-
-/* SH3 has unified cache so no special action needed here */
-#define flush_cache_sigtramp(vaddr)            do { } while (0)
-#define flush_page_to_ram(page)                        do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
-
-#define p3_cache_init()                                do { } while (0)
-
 #define PG_mapped      PG_arch_1
 
-/* We provide our own get_unmapped_area to avoid cache alias issue */
-#define HAVE_ARCH_UNMAPPED_AREA
-
+void flush_cache_all(void);
+void flush_cache_mm(struct mm_struct *mm);
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+                              unsigned long end);
+void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
+void flush_dcache_page(struct page *pg);
+void flush_icache_range(unsigned long start, unsigned long end);
+void flush_icache_page(struct vm_area_struct *vma, struct page *page);
 #else
-
 #define flush_cache_all()                      do { } while (0)
 #define flush_cache_mm(mm)                     do { } while (0)
 #define flush_cache_range(vma, start, end)     do { } while (0)
 #define flush_cache_page(vma, vmaddr, pfn)     do { } while (0)
 #define flush_dcache_page(page)                        do { } while (0)
-#define flush_dcache_mmap_lock(mapping)                do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 #define flush_icache_range(start, end)         do { } while (0)
 #define flush_icache_page(vma,pg)              do { } while (0)
-#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
-#define flush_cache_sigtramp(vaddr)            do { } while (0)
+#endif
 
-#define p3_cache_init()                                do { } while (0)
+#define flush_dcache_mmap_lock(mapping)                do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
-#define HAVE_ARCH_UNMAPPED_AREA
+/* SH3 has unified cache so no special action needed here */
+#define flush_cache_sigtramp(vaddr)            do { } while (0)
+#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
 
-#endif
+#define p3_cache_init()                                do { } while (0)
 
 #endif /* __ASM_CPU_SH3_CACHEFLUSH_H */
-
index b61b6e331df0efa74342de3dbc93c477a10c81b5..273f3229785cfb93076c9ad810b7b68feb474492 100644 (file)
@@ -18,5 +18,9 @@
 #define MIN_DIVISOR_NR         0
 #define MAX_DIVISOR_NR         4
 
+#define FRQCR_CKOEN    0x0100
+#define FRQCR_PLLEN    0x0080
+#define FRQCR_PSTBY    0x0040
+
 #endif /* __ASM_CPU_SH3_FREQ_H */
 
index a844ea0965b6bb10d861e8eff63d045559334532..bccb7ddb438b9ca10bbe7f3d86a9dc9fa3d69255 100644 (file)
 #define TRA    0xffffffd0
 #define EXPEVT 0xffffffd4
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705)
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7706) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7300) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+    defined(CONFIG_CPU_SUBTYPE_SH7710)
 #define INTEVT 0xa4000000      /* INTEVTE2(0xa4000000) */
 #else
 #define INTEVT 0xffffffd8
diff --git a/include/asm-sh/cpu-sh3/shmparam.h b/include/asm-sh/cpu-sh3/shmparam.h
deleted file mode 100644 (file)
index da5b5ee..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-sh/cpu-sh3/shmparam.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_CPU_SH3_SHMPARAM_H
-#define __ASM_CPU_SH3_SHMPARAM_H
-
-#define        SHMLBA PAGE_SIZE                 /* attach addr a multiple of this */
-
-#endif /* __ASM_CPU_SH3_SHMPARAM_H */
-
index 3d8e95e8d10ccd8c8d1666b47759c87b543ff696..b2394cf76f491e21012853302efcf401f6bd8f44 100644 (file)
  *     SH7710
  *     SH7720
  *     SH7300
+ *     SH7710
  * ---------------------------------------------------------------------------
  */
 
+#if !defined(CONFIG_CPU_SUBTYPE_SH7727)
+#define TMU_TOCR       0xfffffe90      /* Byte access */
+#endif
+
 #if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7710)
 #define TMU_TSTR       0xa412fe92      /* Byte access */
 
@@ -39,9 +44,6 @@
 #define TMU2_TCR       0xa412feb4      /* Word access */
 
 #else
-#if !defined(CONFIG_CPU_SUBTYPE_SH7727)
-#define TMU_TOCR       0xfffffe90      /* Byte access */
-#endif
 #define TMU_TSTR       0xfffffe92      /* Byte access */
 
 #define TMU0_TCOR      0xfffffe94      /* Long access */
index 0f809dec4e171a15e55c7b7db4ae05cc70b7c4f0..9d308cbe9b29240064030fb9004a456123e46dba 100644 (file)
 #ifndef __ASM_CPU_SH3_UBC_H
 #define __ASM_CPU_SH3_UBC_H
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+#define UBC_BARA               0xa4ffffb0
+#define UBC_BAMRA              0xa4ffffb4
+#define UBC_BBRA               0xa4ffffb8
+#define UBC_BASRA              0xffffffe4
+#define UBC_BARB               0xa4ffffa0
+#define UBC_BAMRB              0xa4ffffa4
+#define UBC_BBRB               0xa4ffffa8
+#define UBC_BASRB              0xffffffe8
+#define UBC_BDRB               0xa4ffff90
+#define UBC_BDMRB              0xa4ffff94
+#define UBC_BRCR               0xa4ffff98
+#else
 #define UBC_BARA                0xffffffb0
 #define UBC_BAMRA               0xffffffb4
 #define UBC_BBRA                0xffffffb8
@@ -22,6 +35,6 @@
 #define UBC_BDRB                0xffffff90
 #define UBC_BDMRB               0xffffff94
 #define UBC_BRCR                0xffffff98
+#endif
 
 #endif /* __ASM_CPU_SH3_UBC_H */
-
index 727634d886cecdef1fc859e0889d23dbaf7f289b..bb2e1b03060c98b0497527d6ea95413010b302aa 100644 (file)
@@ -22,5 +22,8 @@
 #define P4SEG_TLB_DATA 0xf7000000
 #define P4SEG_REG_BASE 0xff000000
 
+#define PA_AREA5_IO    0xb4000000      /* Area 5 IO Memory */
+#define PA_AREA6_IO    0xb8000000      /* Area 6 IO Memory */
+
 #endif /* __ASM_CPU_SH4_ADDRSPACE_H */
 
index 1fe20359312c774be67ac4ccd2cebcf1dccb9e85..6e9c7e6ee8e4e025d749ad1dbbce65a2cdb76198 100644 (file)
@@ -22,7 +22,9 @@
 #define CCR_CACHE_ICE  0x0100  /* Instruction Cache Enable */
 #define CCR_CACHE_ICI  0x0800  /* IC Invalidate */
 #define CCR_CACHE_IIX  0x8000  /* IC Index Enable */
+#ifndef CONFIG_CPU_SUBTYPE_SH7780
 #define CCR_CACHE_EMODE        0x80000000      /* EMODE Enable */
+#endif
 
 /* Default CCR setup: 8k+16k-byte cache,P1-wb,enable */
 #define CCR_CACHE_ENABLE       (CCR_CACHE_OCE|CCR_CACHE_ICE)
index f323567e085f408f5a3efc5b04a56eb64998b97f..515fd574267c100dba1394ddf48445f67914aeb8 100644 (file)
  *  caching; in which case they're only semi-broken),
  *  so we need them.
  */
-
-/* Page is 4K, OC size is 16K, there are four lines. */
-#define CACHE_ALIAS 0x00003000
-
-struct page;
-struct mm_struct;
-struct vm_area_struct;
-
-extern void flush_cache_all(void);
-extern void flush_cache_mm(struct mm_struct *mm);
-extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
-                             unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
-extern void flush_dcache_page(struct page *pg);
+void flush_cache_all(void);
+void flush_cache_mm(struct mm_struct *mm);
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+                      unsigned long end);
+void flush_cache_page(struct vm_area_struct *vma, unsigned long addr,
+                     unsigned long pfn);
+void flush_dcache_page(struct page *pg);
 
 #define flush_dcache_mmap_lock(mapping)                do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)      do { } while (0)
 
-extern void flush_icache_range(unsigned long start, unsigned long end);
-extern void flush_cache_sigtramp(unsigned long addr);
-extern void flush_icache_user_range(struct vm_area_struct *vma,
-                                   struct page *page, unsigned long addr,
-                                   int len);
+void flush_icache_range(unsigned long start, unsigned long end);
+void flush_cache_sigtramp(unsigned long addr);
+void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
+                            unsigned long addr, int len);
 
 #define flush_icache_page(vma,pg)              do { } while (0)
 
 /* Initialization of P3 area for copy_user_page */
-extern void p3_cache_init(void);
+void p3_cache_init(void);
 
 #define PG_mapped      PG_arch_1
 
-/* We provide our own get_unmapped_area to avoid cache alias issue */
-#define HAVE_ARCH_UNMAPPED_AREA
-
 #ifdef CONFIG_MMU
 extern int remap_area_pages(unsigned long addr, unsigned long phys_addr,
                            unsigned long size, unsigned long flags);
@@ -61,4 +50,3 @@ static inline int remap_area_pages(unsigned long addr, unsigned long phys_addr,
 }
 #endif /* CONFIG_MMU */
 #endif /* __ASM_CPU_SH4_CACHEFLUSH_H */
-
diff --git a/include/asm-sh/cpu-sh4/dma-sh7780.h b/include/asm-sh/cpu-sh4/dma-sh7780.h
new file mode 100644 (file)
index 0000000..6c90d28
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef __ASM_SH_CPU_SH4_DMA_SH7780_H
+#define __ASM_SH_CPU_SH4_DMA_SH7780_H
+
+#define REQ_HE 0x000000C0
+#define REQ_H  0x00000080
+#define REQ_LE 0x00000040
+#define TM_BURST 0x0000020
+#define TS_8   0x00000000
+#define TS_16  0x00000008
+#define TS_32  0x00000010
+#define TS_16BLK       0x00000018
+#define TS_32BLK       0x00100000
+
+/*
+ * The SuperH DMAC supports a number of transmit sizes, we list them here,
+ * with their respective values as they appear in the CHCR registers.
+ *
+ * Defaults to a 64-bit transfer size.
+ */
+enum {
+       XMIT_SZ_8BIT,
+       XMIT_SZ_16BIT,
+       XMIT_SZ_32BIT,
+       XMIT_SZ_128BIT,
+       XMIT_SZ_256BIT,
+};
+
+/*
+ * The DMA count is defined as the number of bytes to transfer.
+ */
+static unsigned int __attribute__ ((used)) ts_shift[] = {
+       [XMIT_SZ_8BIT]          = 0,
+       [XMIT_SZ_16BIT]         = 1,
+       [XMIT_SZ_32BIT]         = 2,
+       [XMIT_SZ_128BIT]        = 4,
+       [XMIT_SZ_256BIT]        = 5,
+};
+
+#endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */
index 0dfe61f14802168b3a6526f821447d0955dc7336..3e4b3e6d80c02fb81b8e03dd882eb10c11ca99ab 100644 (file)
@@ -1,11 +1,17 @@
 #ifndef __ASM_CPU_SH4_DMA_H
 #define __ASM_CPU_SH4_DMA_H
 
+#define DMAOR_INIT     ( 0x8000 | DMAOR_DME )
+
 #ifdef CONFIG_CPU_SH4A
 #define SH_DMAC_BASE   0xfc808020
+
+#define CHCR_TS_MASK   0x18
+#define CHCR_TS_SHIFT  3
+
+#include <asm/cpu/dma-sh7780.h>
 #else
 #define SH_DMAC_BASE   0xffa00000
-#endif
 
 /* Definitions for the SuperH DMAC */
 #define TM_BURST       0x0000080
@@ -19,8 +25,6 @@
 
 #define DMAOR_COD      0x00000008
 
-#define DMAOR_INIT     ( 0x8000 | DMAOR_DME )
-
 /*
  * The SuperH DMAC supports a number of transmit sizes, we list them here,
  * with their respective values as they appear in the CHCR registers.
@@ -45,5 +49,6 @@ static unsigned int ts_shift[] __attribute__ ((used)) = {
        [XMIT_SZ_32BIT]         = 2,
        [XMIT_SZ_256BIT]        = 5,
 };
+#endif
 
 #endif /* __ASM_CPU_SH4_DMA_H */
diff --git a/include/asm-sh/cpu-sh4/shmparam.h b/include/asm-sh/cpu-sh4/shmparam.h
deleted file mode 100644 (file)
index a5a0aa9..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * include/asm-sh/cpu-sh4/shmparam.h
- *
- * Copyright (C) 1999 Niibe Yutaka
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#ifndef __ASM_CPU_SH4_SHMPARAM_H
-#define __ASM_CPU_SH4_SHMPARAM_H
-
-/*
- * SH-4 has D-cache alias issue
- */
-#define        SHMLBA (PAGE_SIZE*4)             /* attach addr a multiple of this */
-
-#endif /* __ASM_CPU_SH4_SHMPARAM_H */
-
index 366b09166d3b738bd7e56bbd52a5a47a8eeb107c..586d6491816aed1fa0741eeaffeab31fb4eb0586 100644 (file)
@@ -17,7 +17,7 @@
  * Store queues range from e0000000-e3fffffc, allowing approx. 64MB to be
  * mapped to any physical address space. Since data is written (and aligned)
  * to 32-byte boundaries, we need to be sure that all allocations are aligned.
- */ 
+ */
 #define SQ_SIZE                 32
 #define SQ_ALIGN_MASK           (~(SQ_SIZE - 1))
 #define SQ_ALIGN(addr)          (((addr)+SQ_SIZE-1) & SQ_ALIGN_MASK)
 #define SQ_QACR1               (P4SEG_REG_BASE  + 0x3c)
 #define SQ_ADDRMAX              (P4SEG_STORE_QUE + 0x04000000)
 
-struct sq_mapping {
-       const char *name;
-
-       unsigned long sq_addr;
-       unsigned long addr;
-       unsigned int size;
-
-       struct list_head list;
-};
-
 /* arch/sh/kernel/cpu/sh4/sq.c */
-extern struct sq_mapping *sq_remap(unsigned long phys, unsigned int size, const char *name);
-extern void sq_unmap(struct sq_mapping *map);
-
-extern void sq_clear(unsigned long addr, unsigned int len);
-extern void sq_flush(void *addr);
-extern void sq_flush_range(unsigned long start, unsigned int len);
+unsigned long sq_remap(unsigned long phys, unsigned int size,
+                      const char *name, unsigned long flags);
+void sq_unmap(unsigned long vaddr);
+void sq_flush_range(unsigned long start, unsigned int len);
 
 #endif /* __ASM_CPU_SH4_SQ_H */
-
diff --git a/include/asm-sh/cqreek/cqreek.h b/include/asm-sh/cqreek/cqreek.h
deleted file mode 100644 (file)
index 09aecc0..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef __ASM_SH_CQREEK_CQREEK_H
-#define __ASM_SH_CQREEK_CQREEK_H
-
-#define BRIDGE_FEATURE         0x0002
-
-#define BRIDGE_IDE_CTRL                0x0018
-#define BRIDGE_IDE_INTR_LVL            0x001A
-#define BRIDGE_IDE_INTR_MASK   0x001C
-#define BRIDGE_IDE_INTR_STAT   0x001E
-
-#define BRIDGE_ISA_CTRL                0x0028
-#define BRIDGE_ISA_INTR_LVL            0x002A
-#define BRIDGE_ISA_INTR_MASK   0x002C
-#define BRIDGE_ISA_INTR_STAT   0x002E
-
-/* arch/sh/boards/cqreek/setup.c */
-extern void setup_cqreek(void);
-
-/* arch/sh/boards/cqreek/irq.c */
-extern int cqreek_has_ide, cqreek_has_isa;
-extern void init_cqreek_IRQ(void);
-
-/* arch/sh/boards/cqreek/io.c */
-extern unsigned long cqreek_port2addr(unsigned long port);
-
-#endif /* __ASM_SH_CQREEK_CQREEK_H */
-
index 124968f9866e9f2cabeb0d78474a3c2dcaf1f2e0..56cd4b97723212bd2a3cd988464f202b34911f91 100644 (file)
@@ -141,25 +141,35 @@ static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
        }
 }
 
-static void dma_sync_single_for_cpu(struct device *dev,
-                                   dma_addr_t dma_handle, size_t size,
-                                   enum dma_data_direction dir)
-       __attribute__ ((alias("dma_sync_single")));
+static inline void dma_sync_single_for_cpu(struct device *dev,
+                                          dma_addr_t dma_handle, size_t size,
+                                          enum dma_data_direction dir)
+{
+       dma_sync_single(dev, dma_handle, size, dir);
+}
+
+static inline void dma_sync_single_for_device(struct device *dev,
+                                             dma_addr_t dma_handle,
+                                             size_t size,
+                                             enum dma_data_direction dir)
+{
+       dma_sync_single(dev, dma_handle, size, dir);
+}
 
-static void dma_sync_single_for_device(struct device *dev,
-                                      dma_addr_t dma_handle, size_t size,
+static inline void dma_sync_sg_for_cpu(struct device *dev,
+                                      struct scatterlist *sg, int nelems,
                                       enum dma_data_direction dir)
-       __attribute__ ((alias("dma_sync_single")));
+{
+       dma_sync_sg(dev, sg, nelems, dir);
+}
 
-static void dma_sync_sg_for_cpu(struct device *dev,
-                               struct scatterlist *sg, int nelems,
-                               enum dma_data_direction dir)
-       __attribute__ ((alias("dma_sync_sg")));
+static inline void dma_sync_sg_for_device(struct device *dev,
+                                         struct scatterlist *sg, int nelems,
+                                         enum dma_data_direction dir)
+{
+       dma_sync_sg(dev, sg, nelems, dir);
+}
 
-static void dma_sync_sg_for_device(struct device *dev,
-                                  struct scatterlist *sg, int nelems,
-                                  enum dma_data_direction dir)
-       __attribute__ ((alias("dma_sync_sg")));
 
 static inline int dma_get_cache_alignment(void)
 {
@@ -174,6 +184,4 @@ static inline int dma_mapping_error(dma_addr_t dma_addr)
 {
        return dma_addr == 0;
 }
-
 #endif /* __ASM_SH_DMA_MAPPING_H */
-
index e62a6d0ed932cec3631ee42e1d3e51331d09ae23..d9daa028689f91b675583c892c00aa48925b4534 100644 (file)
@@ -89,6 +89,7 @@ struct dma_channel {
        wait_queue_head_t wait_queue;
 
        struct sys_device dev;
+       char *name;
 };
 
 struct dma_info {
diff --git a/include/asm-sh/dmida/io.h b/include/asm-sh/dmida/io.h
deleted file mode 100644 (file)
index 21bd416..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __ASM_SH_DMIDA_IO_H
-#define __ASM_SH_DMIDA_IO_H
-
-/*
- * Nothing special here.. just use the generic cchip io routines.
- */
-#include <asm/hd64465/io.h>
-
-#endif /* __ASM_SH_DMIDA_IO_H */
-
index 1b63dfeea4f2b3e165a4689e80c130a46b6eb1c0..3a07ab40ac4d0a66eab64eb094f538e08fef68bb 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef __ASM_SH_ELF_H
 #define __ASM_SH_ELF_H
 
+#include <asm/processor.h>
+#include <asm/auxvec.h>
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
 /* SH relocation types  */
 #define        R_SH_NONE               0
 #define        R_SH_DIR32              1
@@ -46,9 +51,6 @@
  * ELF register definitions..
  */
 
-#include <asm/ptrace.h>
-#include <asm/user.h>
-
 typedef unsigned long elf_greg_t;
 
 #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
@@ -91,7 +93,7 @@ typedef struct user_fpu_struct elf_fpregset_t;
    instruction set this CPU supports.  This could be done in user space,
    but it's not easy, and we've already done it here.  */
 
-#define ELF_HWCAP      (0)
+#define ELF_HWCAP      (boot_cpu_data.flags)
 
 /* This yields a string that ld.so will use to load implementation
    specific libraries for optimization.  This is more specific in
@@ -119,4 +121,24 @@ extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
 #endif
 
+#ifdef CONFIG_VSYSCALL
+/* vDSO has arch_setup_additional_pages */
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm,
+                                      int executable_stack);
+
+extern unsigned int vdso_enabled;
+extern void __kernel_vsyscall;
+
+#define VDSO_BASE              ((unsigned long)current->mm->context.vdso)
+#define VDSO_SYM(x)            (VDSO_BASE + (unsigned long)(x))
+
+#define ARCH_DLINFO                                            \
+do {                                                           \
+       if (vdso_enabled)                                       \
+               NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE);        \
+} while (0)
+#endif /* CONFIG_VSYSCALL */
+
 #endif /* __ASM_SH_ELF_H */
index 412bccaa07e6ee8ffddaf7e7afc0570df0db9f2f..458e9fa59545e309225c10d11a6f1e1575816926 100644 (file)
@@ -25,7 +25,7 @@
  * addresses. The point is to have a constant address at
  * compile time, but to set the physical address only
  * in the boot process. We allocate these special  addresses
- * from the end of virtual memory (0xfffff000) backwards.
+ * from the end of P3 backwards.
  * Also this lets us do fail-safe vmalloc(), we
  * can guarantee that these special addresses and
  * vmalloc()-ed addresses never overlap.
index f29072e1c87e97e8ab3227d09f67cee4c0b22d68..0d5cc04ab005db06809770d4b551c4475382569e 100644 (file)
@@ -13,7 +13,7 @@
 #define __ASM_SH_FLAT_H
 
 #define        flat_stack_align(sp)                    /* nothing needed */
-#define        flat_argvp_envp_on_stack()              1
+#define        flat_argvp_envp_on_stack()              0
 #define        flat_old_ram_flag(flags)                (flags)
 #define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
 #define        flat_get_addr_from_rp(rp, relval, flags)        get_unaligned(rp)
diff --git a/include/asm-sh/harp/harp.h b/include/asm-sh/harp/harp.h
deleted file mode 100644 (file)
index b2fbcfa..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 
- * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- * Defintions applicable to the STMicroelectronics ST40STB1 HARP and
- * compatible boards.
- */
-
-#if defined(CONFIG_SH_STB1_HARP)
-
-#define EPLD_BASE     0xa0800000
-
-#define EPLD_LED      (EPLD_BASE+0x000c0000)
-#define EPLD_INTSTAT0 (EPLD_BASE+0x00200000)
-#define EPLD_INTSTAT1 (EPLD_BASE+0x00240000)
-#define EPLD_INTMASK0 (EPLD_BASE+0x00280000)
-#define EPLD_INTMASK1 (EPLD_BASE+0x002c0000)
-#define EPLD_PAGEADDR (EPLD_BASE+0x00300000)
-#define EPLD_REVID1   (EPLD_BASE+0x00380000)
-#define EPLD_REVID2   (EPLD_BASE+0x003c0000)
-
-#define EPLD_LED_ON  1
-#define EPLD_LED_OFF 0
-
-#elif defined(CONFIG_SH_STB1_OVERDRIVE)
-
-#define EPLD_BASE     0xa7000000
-
-#define EPLD_REVID    (EPLD_BASE+0x00000000)
-#define EPLD_LED      (EPLD_BASE+0x00040000)
-#define EPLD_INTMASK0 (EPLD_BASE+0x001c0000)
-#define EPLD_INTMASK1 (EPLD_BASE+0x00200000)
-#define EPLD_INTSTAT0 (EPLD_BASE+0x00240000)
-#define EPLD_INTSTAT1 (EPLD_BASE+0x00280000)
-
-#define EPLD_LED_ON  0
-#define EPLD_LED_OFF 1
-
-#else
-#error Unknown board
-#endif
diff --git a/include/asm-sh/harp/io.h b/include/asm-sh/harp/io.h
deleted file mode 100644 (file)
index 68f39e0..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __ASM_SH_HARP_IO_H
-#define __ASM_SH_HARP_IO_H
-
-/*
- * Nothing special here.. just use the generic cchip io routines.
- */
-#include <asm/hd64465/io.h>
-
-#endif /* __ASM_SH_HARP_IO_H */
-
similarity index 84%
rename from include/asm-sh/hd64461/hd64461.h
rename to include/asm-sh/hd64461.h
index 87f13d24c630ac5bf2a7a973340d90a8c5e2bff4..27e5c34e265991a54410513c97a7a210c550b3dd 100644 (file)
 #define HD64461_LCDCBAR                0x11000
 #define HD64461_LCDCLOR                0x11002
 #define HD64461_LCDCCR         0x11004
-#define HD64461_LCDCCR_MOFF    0x80
+#define HD64461_LCDCCR_STBACK  0x0400
+#define HD64461_LCDCCR_STREQ   0x0100
+#define HD64461_LCDCCR_MOFF    0x0080
+#define HD64461_LCDCCR_REFSEL  0x0040
+#define HD64461_LCDCCR_EPON    0x0020
+#define HD64461_LCDCCR_SPON    0x0010
 
 #define        HD64461_LDR1            0x11010
 #define        HD64461_LDR1_DON        0x01
@@ -54,9 +59,9 @@
 #define HD64461_LDVSPR         0x1101c
 #define HD64461_LDR3           0x1101e
 
-#define HD64461_CPTWAR         0x11030 
+#define HD64461_CPTWAR         0x11030
 #define HD64461_CPTWDR         0x11032
-#define HD64461_CPTRAR         0x11034 
+#define HD64461_CPTRAR         0x11034
 #define HD64461_CPTRDR         0x11036
 
 #define HD64461_GRDOR          0x11040
 #define HD64461_PCCISR_BVD1            0x01    /* battery 1 */
 
 #define HD64461_PCCISR_PCD_MASK                0x0c    /* card detect */
-#define HD64461_PCCISR_BVD_MASK        0x03    /* battery voltage */
+#define HD64461_PCCISR_BVD_MASK                0x03    /* battery voltage */
 #define HD64461_PCCISR_BVD_BATGOOD     0x03    /* battery good */
 #define HD64461_PCCISR_BVD_BATWARN     0x01    /* battery low warning */
 #define HD64461_PCCISR_BVD_BATDEAD1    0x02    /* battery dead */
 
 /* PCC Card Status Change Interrupt Enable Register */
 #define HD64461_PCCCSCIER_CRE          0x80    /* change reset enable */
-#define HD64461_PCCCSCIER_IREQE_MASK           0x60   /* IREQ enable */
+#define HD64461_PCCCSCIER_IREQE_MASK   0x60   /* IREQ enable */
 #define HD64461_PCCCSCIER_IREQE_DISABLED       0x00   /* IREQ disabled */
-#define HD64461_PCCCSCIER_IREQE_LEVEL          0x20   /* IREQ level-triggered */
+#define HD64461_PCCCSCIER_IREQE_LEVEL  0x20   /* IREQ level-triggered */
 #define HD64461_PCCCSCIER_IREQE_FALLING        0x40   /* IREQ falling-edge-trig */
-#define HD64461_PCCCSCIER_IREQE_RISING         0x60   /* IREQ rising-edge-trig */
+#define HD64461_PCCCSCIER_IREQE_RISING 0x60   /* IREQ rising-edge-trig */
 
 #define HD64461_PCCCSCIER_SCE          0x10    /* status change enable */
 #define HD64461_PCCCSCIER_CDE          0x08    /* card detect change enable */
 #define HD64461_PCCSCR_VCC1            0x02    /* voltage control pin 1 */
 #define HD64461_PCCSCR_SWP             0x01    /* write protect */
 
-
 #define HD64461_P0OCR           0x1202a
 #define HD64461_P1OCR           0x1202c
 #define HD64461_PGCR            0x1202e
 #define HD64461_NIRR           0x15000
 #define HD64461_NIMR           0x15002
 
-#ifndef CONFIG_HD64461_IOBASE
-#define CONFIG_HD64461_IOBASE  0xb0000000
-#endif
-#ifndef CONFIG_HD64461_IRQ
-#define CONFIG_HD64461_IRQ     36
-#endif
-
 #define HD64461_IRQBASE                OFFCHIP_IRQ_BASE
-#define HD64461_IRQ_NUM        16
-
-#define HD64461_IRQ_UART       (HD64461_IRQBASE+5)
-#define HD64461_IRQ_IRDA       (HD64461_IRQBASE+6)
-#define HD64461_IRQ_TMU1       (HD64461_IRQBASE+9)
-#define HD64461_IRQ_TMU0       (HD64461_IRQBASE+10)
-#define HD64461_IRQ_GPIO       (HD64461_IRQBASE+11)
-#define HD64461_IRQ_AFE        (HD64461_IRQBASE+12)
-#define HD64461_IRQ_PCC1       (HD64461_IRQBASE+13)
-#define HD64461_IRQ_PCC0       (HD64461_IRQBASE+14)
+#define HD64461_IRQ_NUM                16
+
+#define HD64461_IRQ_UART       (HD64461_IRQBASE+5)
+#define HD64461_IRQ_IRDA       (HD64461_IRQBASE+6)
+#define HD64461_IRQ_TMU1       (HD64461_IRQBASE+9)
+#define HD64461_IRQ_TMU0       (HD64461_IRQBASE+10)
+#define HD64461_IRQ_GPIO       (HD64461_IRQBASE+11)
+#define HD64461_IRQ_AFE                (HD64461_IRQBASE+12)
+#define HD64461_IRQ_PCC1       (HD64461_IRQBASE+13)
+#define HD64461_IRQ_PCC0       (HD64461_IRQBASE+14)
+
+#define __IO_PREFIX    hd64461
+#include <asm/io_generic.h>
+
+/* arch/sh/cchips/hd6446x/hd64461/setup.c */
+int hd64461_irq_demux(int irq);
+void hd64461_register_irq_demux(int irq,
+                               int (*demux) (int irq, void *dev), void *dev);
+void hd64461_unregister_irq_demux(int irq);
 
 #endif
diff --git a/include/asm-sh/hd64461/io.h b/include/asm-sh/hd64461/io.h
deleted file mode 100644 (file)
index 67f2489..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * include/asm-sh/io_hd64461.h
- *
- * 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 an HD64461
- */
-
-#ifndef _ASM_SH_IO_HD64461_H
-#define _ASM_SH_IO_HD64461_H
-
-extern unsigned char hd64461_inb(unsigned long port);
-extern unsigned short hd64461_inw(unsigned long port);
-extern unsigned int hd64461_inl(unsigned long port);
-
-extern void hd64461_outb(unsigned char value, unsigned long port);
-extern void hd64461_outw(unsigned short value, unsigned long port);
-extern void hd64461_outl(unsigned int value, unsigned long port);
-
-extern unsigned char hd64461_inb_p(unsigned long port);
-extern void hd64461_outb_p(unsigned char value, unsigned long port);
-
-extern void hd64461_insb(unsigned long port, void *addr, unsigned long count);
-extern void hd64461_insw(unsigned long port, void *addr, unsigned long count);
-extern void hd64461_insl(unsigned long port, void *addr, unsigned long count);
-
-extern void hd64461_outsb(unsigned long port, const void *buffer, unsigned long count);
-extern void hd64461_outsw(unsigned long port, const void *buffer, unsigned long count);
-extern void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count);
-
-extern unsigned short hd64461_readw(unsigned long addr);
-extern void hd64461_writew(unsigned short b, unsigned long addr);
-
-
-extern int hd64461_irq_demux(int irq);
-extern void hd64461_register_irq_demux(int irq,
-               int (*demux)(int irq, void *dev), void *dev);
-extern void hd64461_unregister_irq_demux(int irq);
-
-#endif /* _ASM_SH_IO_HD64461_H */
index a26247fd3d87ca744ca0d91ae451808a9b242cc9..f35134c159dd103aec724d75d61be8f923fda357 100644 (file)
@@ -2,16 +2,33 @@
 #define __ASM_SH_HP6XX_H
 
 /*
- * Copyright (C) 2003  Andriy Skulysh
+ * Copyright (C) 2003, 2004, 2005  Andriy Skulysh
+ *
+ * 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.
+ *
  */
 
-#define HP680_TS_IRQ IRQ3_IRQ
+#define HP680_BTN_IRQ          IRQ0_IRQ
+#define HP680_TS_IRQ           IRQ3_IRQ
+#define HP680_HD64461_IRQ      IRQ4_IRQ
 
 #define DAC_LCD_BRIGHTNESS     0
 #define DAC_SPEAKER_VOLUME     1
 
+#define PGDR_OPENED            0x01
+#define PGDR_MAIN_BATTERY_OUT  0x04
+#define PGDR_PLAY_BUTTON       0x08
+#define PGDR_REWIND_BUTTON     0x10
+#define PGDR_RECORD_BUTTON     0x20
+
 #define PHDR_TS_PEN_DOWN       0x08
 
+#define PJDR_LED_BLINK         0x02
+
+#define PKDR_LED_GREEN         0x10
+
 #define SCPDR_TS_SCAN_ENABLE   0x20
 #define SCPDR_TS_SCAN_Y                0x02
 #define SCPDR_TS_SCAN_X                0x01
 
 #define ADC_CHANNEL_TS_Y       1
 #define ADC_CHANNEL_TS_X       2
+#define ADC_CHANNEL_BATTERY    3
+#define ADC_CHANNEL_BACKUP     4
+#define ADC_CHANNEL_CHARGE     5
 
 #define HD64461_GPADR_SPEAKER  0x01
 #define HD64461_GPADR_PCMCIA0  (0x02|0x08)
+
 #define HD64461_GPBDR_LCDOFF   0x01
+#define HD64461_GPBDR_LCD_CONTRAST_MASK        0x78
 #define HD64461_GPBDR_LED_RED  0x80
 
+#include <asm/hd64461.h>
+#include <asm/io.h>
+
+#define PJDR   0xa4000130
+#define PKDR   0xa4000132
+
+static inline void hp6xx_led_red(int on)
+{
+       u16 v16;
+       v16 = ctrl_inw(CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000);
+       if (on)
+           ctrl_outw(v16 & (~HD64461_GPBDR_LED_RED), CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000);
+       else
+           ctrl_outw(v16 | HD64461_GPBDR_LED_RED, CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000);
+}
+
+static inline void hp6xx_led_green(int on)
+{
+       u8 v8;
+
+       v8 = ctrl_inb(PKDR);
+       if (on)
+           ctrl_outb(v8 & (~PKDR_LED_GREEN), PKDR);
+       else
+           ctrl_outb(v8 | PKDR_LED_GREEN, PKDR);
+}
+
 
 #endif /* __ASM_SH_HP6XX_H */
index 7317980035503c0690ccf20eb561fa644b248da9..2044476ab199ea2952cdee71831a4617254f648b 100644 (file)
@@ -4,7 +4,7 @@
 /*
  * Nothing special here.. just use the generic cchip io routines.
  */
-#include <asm/hd64461/io.h>
+#include <asm/hd64461.h>
 
 #endif /* __ASM_SH_HP6XX_IO_H */
 
index 5f995f937a441dc207f1d88960077752b2604444..c4cff9d33927d95bfe234487b01b8cb4caecc9df 100644 (file)
@@ -19,8 +19,6 @@
 #define PA_OUTPORTR    0xa400000e      /* Output Port Reguster */
 #define PA_VERREG      0xa4000014      /* FPGA Version Register */
 
-#define PA_AREA5_IO    0xb4000000      /* Area 5 IO Memory */
-#define PA_AREA6_IO    0xb8000000      /* Area 6 IO Memory */
 #define PA_IDE_OFFSET  0x1f0           /* CF IDE Offset */
 
 #define IRLCNTR1       (PA_BCR + 0)    /* Interrupt Control Register1 */
 #define        IRQ_RINGING     4               /* Ringing IRQ */
 #define        IRQ_CODEC       5               /* CODEC IRQ */
 
+#define __IO_PREFIX    hs7751rvoip
+#include <asm/io_generic.h>
+
+/* arch/sh/boards/renesas/hs7751rvoip/irq.c */
+void init_hs7751rvoip_IRQ(void);
+
+/* arch/sh/boards/renesas/hs7751rvoip/io.c */
+void *hs7751rvoip_ioremap(unsigned long, unsigned long);
+
 #endif  /* __ASM_SH_RENESAS_HS7751RVOIP */
index 894e64b2d5f0a0f066c50f2fca4a9dc554f172dd..ed12d38e8c0082dda8db85613bf578f4819e3ef9 100644 (file)
 #define __raw_writew(v, a)     __writew(v, (void __iomem *)(a))
 #define __raw_writel(v, a)     __writel(v, (void __iomem *)(a))
 
+void __raw_writesl(unsigned long addr, const void *data, int longlen);
+void __raw_readsl(unsigned long addr, void *data, int longlen);
+
 /*
  * The platform header files may define some of these macros to use
  * the inlined versions where appropriate.  These macros may also be
 # define writel(v,a)   ({ __raw_writel((v),(a)); mb(); })
 #endif
 
+#define writesl __raw_writesl
+#define readsl  __raw_readsl
+
 #define readb_relaxed(a) readb(a)
 #define readw_relaxed(a) readw(a)
 #define readl_relaxed(a) readl(a)
@@ -209,8 +215,14 @@ static inline void ctrl_outl(unsigned int b, unsigned long addr)
         *(volatile unsigned long*)addr = b;
 }
 
+static inline void ctrl_delay(void)
+{
+       ctrl_inw(P2SEG);
+}
+
 #define IO_SPACE_LIMIT 0xffffffff
 
+#ifdef CONFIG_MMU
 /*
  * Change virtual addresses to physical addresses and vv.
  * These are trivial on the 1:1 Linux/SuperH mapping
@@ -224,6 +236,10 @@ static inline void *phys_to_virt(unsigned long address)
 {
        return (void *)P1SEGADDR(address);
 }
+#else
+#define phys_to_virt(address)  ((void *)(address))
+#define virt_to_phys(address)  ((unsigned long)(address))
+#endif
 
 #define virt_to_bus virt_to_phys
 #define bus_to_virt phys_to_virt
index d705252be260018902a68df8464b1730f7f0cdc9..b28af9a69d728d7dbc074f10bac3b91de9481845 100644 (file)
 #define IRQ6_PRIORITY  1
 #define IRQ7_PRIORITY  1
 
-int shmse_irq_demux(int irq);
-
 #endif /* __ASM_SH_IRQ_SH73180_H */
diff --git a/include/asm-sh/irq-sh7343.h b/include/asm-sh/irq-sh7343.h
new file mode 100644 (file)
index 0000000..5d15419
--- /dev/null
@@ -0,0 +1,317 @@
+#ifndef __ASM_SH_IRQ_SH7343_H
+#define __ASM_SH_IRQ_SH7343_H
+
+/*
+ * linux/include/asm-sh/irq-sh7343.h
+ *
+ * Copyright (C) 2006 Kenati Technologies Inc.
+ * Andre Mccurdy <andre@kenati.com>
+ * Ranjit Deshpande <ranjit@kenati.com>
+ */
+
+#undef INTC_IPRA
+#undef INTC_IPRB
+#undef INTC_IPRC
+#undef INTC_IPRD
+
+#undef DMTE0_IRQ
+#undef DMTE1_IRQ
+#undef DMTE2_IRQ
+#undef DMTE3_IRQ
+#undef DMTE4_IRQ
+#undef DMTE5_IRQ
+#undef DMTE6_IRQ
+#undef DMTE7_IRQ
+#undef DMAE_IRQ
+#undef DMA_IPR_ADDR
+#undef DMA_IPR_POS
+#undef DMA_PRIORITY
+
+#undef INTC_IMCR0
+#undef INTC_IMCR1
+#undef INTC_IMCR2
+#undef INTC_IMCR3
+#undef INTC_IMCR4
+#undef INTC_IMCR5
+#undef INTC_IMCR6
+#undef INTC_IMCR7
+#undef INTC_IMCR8
+#undef INTC_IMCR9
+#undef INTC_IMCR10
+
+
+#define INTC_IPRA      0xA4080000UL
+#define INTC_IPRB      0xA4080004UL
+#define INTC_IPRC      0xA4080008UL
+#define INTC_IPRD      0xA408000CUL
+#define INTC_IPRE      0xA4080010UL
+#define INTC_IPRF      0xA4080014UL
+#define INTC_IPRG      0xA4080018UL
+#define INTC_IPRH      0xA408001CUL
+#define INTC_IPRI      0xA4080020UL
+#define INTC_IPRJ      0xA4080024UL
+#define INTC_IPRK      0xA4080028UL
+#define INTC_IPRL      0xA408002CUL
+
+#define INTC_IMR0      0xA4080080UL
+#define INTC_IMR1      0xA4080084UL
+#define INTC_IMR2      0xA4080088UL
+#define INTC_IMR3      0xA408008CUL
+#define INTC_IMR4      0xA4080090UL
+#define INTC_IMR5      0xA4080094UL
+#define INTC_IMR6      0xA4080098UL
+#define INTC_IMR7      0xA408009CUL
+#define INTC_IMR8      0xA40800A0UL
+#define INTC_IMR9      0xA40800A4UL
+#define INTC_IMR10     0xA40800A8UL
+#define INTC_IMR11     0xA40800ACUL
+
+#define INTC_IMCR0     0xA40800C0UL
+#define INTC_IMCR1     0xA40800C4UL
+#define INTC_IMCR2     0xA40800C8UL
+#define INTC_IMCR3     0xA40800CCUL
+#define INTC_IMCR4     0xA40800D0UL
+#define INTC_IMCR5     0xA40800D4UL
+#define INTC_IMCR6     0xA40800D8UL
+#define INTC_IMCR7     0xA40800DCUL
+#define INTC_IMCR8     0xA40800E0UL
+#define INTC_IMCR9     0xA40800E4UL
+#define INTC_IMCR10    0xA40800E8UL
+#define INTC_IMCR11    0xA40800ECUL
+
+#define INTC_ICR0      0xA4140000UL
+#define INTC_ICR1      0xA414001CUL
+
+#define INTMSK0                0xa4140044
+#define INTMSKCLR0     0xa4140064
+#define INTC_INTPRI0   0xa4140010
+
+/*
+  NOTE:
+
+  *_IRQ = (INTEVT2 - 0x200)/0x20
+*/
+
+/* TMU0 */
+#define TMU0_IRQ       16
+#define TMU0_IPR_ADDR  INTC_IPRA
+#define TMU0_IPR_POS    3
+#define TMU0_PRIORITY   2
+
+#define TIMER_IRQ       16
+#define TIMER_IPR_ADDR  INTC_IPRA
+#define TIMER_IPR_POS    3
+#define TIMER_PRIORITY   2
+
+/* TMU1 */
+#define TMU1_IRQ       17
+#define TMU1_IPR_ADDR  INTC_IPRA
+#define TMU1_IPR_POS    2
+#define TMU1_PRIORITY   2
+
+/* TMU2 */
+#define TMU2_IRQ       18
+#define TMU2_IPR_ADDR  INTC_IPRA
+#define TMU2_IPR_POS    1
+#define TMU2_PRIORITY   2
+
+/* LCDC */
+#define LCDC_IRQ       28
+#define LCDC_IPR_ADDR  INTC_IPRB
+#define LCDC_IPR_POS    2
+#define LCDC_PRIORITY   2
+
+/* VIO (Video I/O) */
+#define CEU_IRQ                52
+#define BEU_IRQ                53
+#define VEU_IRQ                54
+#define VOU_IRQ                55
+#define VIO_IPR_ADDR   INTC_IPRE
+#define VIO_IPR_POS     2
+#define VIO_PRIORITY    2
+
+/* MFI (Multi Functional Interface) */
+#define MFI_IRQ                56
+#define MFI_IPR_ADDR   INTC_IPRE
+#define MFI_IPR_POS     1
+#define MFI_PRIORITY    2
+
+/* VPU (Video Processing Unit) */
+#define VPU_IRQ                60
+#define VPU_IPR_ADDR   INTC_IPRE
+#define VPU_IPR_POS     0
+#define VPU_PRIORITY    2
+
+/* 3DG */
+#define TDG_IRQ                63
+#define TDG_IPR_ADDR   INTC_IPRJ
+#define TDG_IPR_POS     2
+#define TDG_PRIORITY    2
+
+/* DMAC(1) */
+#define DMTE0_IRQ      48
+#define DMTE1_IRQ      49
+#define DMTE2_IRQ      50
+#define DMTE3_IRQ      51
+#define DMA1_IPR_ADDR  INTC_IPRE
+#define DMA1_IPR_POS   3
+#define DMA1_PRIORITY  7
+
+/* DMAC(2) */
+#define DMTE4_IRQ      76
+#define DMTE5_IRQ      77
+#define DMA2_IPR_ADDR  INTC_IPRF
+#define DMA2_IPR_POS   2
+#define DMA2_PRIORITY  7
+
+/* SCIF0 */
+#define SCIF_ERI_IRQ   80
+#define SCIF_RXI_IRQ   81
+#define SCIF_BRI_IRQ   82
+#define SCIF_TXI_IRQ   83
+#define SCIF_IPR_ADDR  INTC_IPRG
+#define SCIF_IPR_POS   3
+#define SCIF_PRIORITY  3
+
+/* SIOF0 */
+#define SIOF0_IRQ      84
+#define SIOF0_IPR_ADDR INTC_IPRH
+#define SIOF0_IPR_POS  3
+#define SIOF0_PRIORITY 3
+
+/* FLCTL (Flash Memory Controller) */
+#define FLSTE_IRQ      92
+#define FLTEND_IRQ     93
+#define FLTRQ0_IRQ     94
+#define FLTRQ1_IRQ     95
+#define FLCTL_IPR_ADDR INTC_IPRH
+#define FLCTL_IPR_POS  1
+#define FLCTL_PRIORITY 3
+
+/* IIC(0) (IIC Bus Interface) */
+#define IIC0_ALI_IRQ   96
+#define IIC0_TACKI_IRQ 97
+#define IIC0_WAITI_IRQ 98
+#define IIC0_DTEI_IRQ  99
+#define IIC0_IPR_ADDR  INTC_IPRH
+#define IIC0_IPR_POS   0
+#define IIC0_PRIORITY  3
+
+/* IIC(1) (IIC Bus Interface) */
+#define IIC1_ALI_IRQ   44
+#define IIC1_TACKI_IRQ 45
+#define IIC1_WAITI_IRQ 46
+#define IIC1_DTEI_IRQ  47
+#define IIC1_IPR_ADDR  INTC_IPRI
+#define IIC1_IPR_POS   0
+#define IIC1_PRIORITY  3
+
+/* SIO0 */
+#define SIO0_IRQ       88
+#define SIO0_IPR_ADDR  INTC_IPRI
+#define SIO0_IPR_POS   3
+#define SIO0_PRIORITY  3
+
+/* SDHI */
+#define SDHI_SDHII0_IRQ        100
+#define SDHI_SDHII1_IRQ        101
+#define SDHI_SDHII2_IRQ        102
+#define SDHI_SDHII3_IRQ        103
+#define SDHI_IPR_ADDR  INTC_IPRK
+#define SDHI_IPR_POS   0
+#define SDHI_PRIORITY  3
+
+/* SIU (Sound Interface Unit) */
+#define SIU_IRQ                108
+#define SIU_IPR_ADDR   INTC_IPRJ
+#define SIU_IPR_POS    1
+#define SIU_PRIORITY   3
+
+#define PORT_PACR      0xA4050100UL
+#define PORT_PBCR      0xA4050102UL
+#define PORT_PCCR      0xA4050104UL
+#define PORT_PDCR      0xA4050106UL
+#define PORT_PECR      0xA4050108UL
+#define PORT_PFCR      0xA405010AUL
+#define PORT_PGCR      0xA405010CUL
+#define PORT_PHCR      0xA405010EUL
+#define PORT_PJCR      0xA4050110UL
+#define PORT_PKCR      0xA4050112UL
+#define PORT_PLCR      0xA4050114UL
+#define PORT_SCPCR     0xA4050116UL
+#define PORT_PMCR      0xA4050118UL
+#define PORT_PNCR      0xA405011AUL
+#define PORT_PQCR      0xA405011CUL
+#define PORT_PRCR      0xA405011EUL
+#define PORT_PTCR      0xA405014CUL
+#define PORT_PUCR      0xA405014EUL
+#define PORT_PVCR      0xA4050150UL
+
+#define PORT_PSELA     0xA4050140UL
+#define PORT_PSELB     0xA4050142UL
+#define PORT_PSELC     0xA4050144UL
+#define PORT_PSELE     0xA4050158UL
+
+#define PORT_HIZCRA    0xA4050146UL
+#define PORT_HIZCRB    0xA4050148UL
+#define PORT_DRVCR     0xA405014AUL
+
+#define PORT_PADR      0xA4050120UL
+#define PORT_PBDR      0xA4050122UL
+#define PORT_PCDR      0xA4050124UL
+#define PORT_PDDR      0xA4050126UL
+#define PORT_PEDR      0xA4050128UL
+#define PORT_PFDR      0xA405012AUL
+#define PORT_PGDR      0xA405012CUL
+#define PORT_PHDR      0xA405012EUL
+#define PORT_PJDR      0xA4050130UL
+#define PORT_PKDR      0xA4050132UL
+#define PORT_PLDR      0xA4050134UL
+#define PORT_SCPDR     0xA4050136UL
+#define PORT_PMDR      0xA4050138UL
+#define PORT_PNDR      0xA405013AUL
+#define PORT_PQDR      0xA405013CUL
+#define PORT_PRDR      0xA405013EUL
+#define PORT_PTDR      0xA405016CUL
+#define PORT_PUDR      0xA405016EUL
+#define PORT_PVDR      0xA4050170UL
+
+#define IRQ0_IRQ       32
+#define IRQ1_IRQ       33
+#define IRQ2_IRQ       34
+#define IRQ3_IRQ       35
+#define IRQ4_IRQ       36
+#define IRQ5_IRQ       37
+#define IRQ6_IRQ       38
+#define IRQ7_IRQ       39
+
+#define INTPRI00       0xA4140010UL
+
+#define IRQ0_IPR_ADDR  INTPRI00
+#define IRQ1_IPR_ADDR  INTPRI00
+#define IRQ2_IPR_ADDR  INTPRI00
+#define IRQ3_IPR_ADDR  INTPRI00
+#define IRQ4_IPR_ADDR  INTPRI00
+#define IRQ5_IPR_ADDR  INTPRI00
+#define IRQ6_IPR_ADDR  INTPRI00
+#define IRQ7_IPR_ADDR  INTPRI00
+
+#define IRQ0_IPR_POS   7
+#define IRQ1_IPR_POS   6
+#define IRQ2_IPR_POS   5
+#define IRQ3_IPR_POS   4
+#define IRQ4_IPR_POS   3
+#define IRQ5_IPR_POS   2
+#define IRQ6_IPR_POS   1
+#define IRQ7_IPR_POS   0
+
+#define IRQ0_PRIORITY  1
+#define IRQ1_PRIORITY  1
+#define IRQ2_PRIORITY  1
+#define IRQ3_PRIORITY  1
+#define IRQ4_PRIORITY  1
+#define IRQ5_PRIORITY  1
+#define IRQ6_PRIORITY  1
+#define IRQ7_PRIORITY  1
+
+#endif /* __ASM_SH_IRQ_SH7343_H */
index 7f90315cd8304359c9d35653fb9709822c3c8ef1..895c5780e45473150ad02217a860e254b7fac648 100644 (file)
 #define        TMU_CH5_IPR_POS         1
 #define TMU_CH5_PRIORITY       2
 
-#define        RTC_IRQ         22
-#define        RTC_IPR_ADDR    INTC_INT2PRI1
-#define        RTC_IPR_POS     0
-#define        RTC_PRIORITY    TIMER_PRIORITY
-
 /* SCIF0 */
 #define SCIF0_ERI_IRQ  40
 #define SCIF0_RXI_IRQ  41
index 611e67cd062728bf08726717ee3ec96858eaf057..0e5f365aff70a63e2f2e639101e5b46e26708ce7 100644 (file)
 
 #if defined (CONFIG_CPU_SUBTYPE_SH7707) || defined (CONFIG_CPU_SUBTYPE_SH7708) || \
     defined (CONFIG_CPU_SUBTYPE_SH7709) || defined (CONFIG_CPU_SUBTYPE_SH7750) || \
-    defined (CONFIG_CPU_SUBTYPE_SH7751)
+    defined (CONFIG_CPU_SUBTYPE_SH7751) || defined (CONFIG_CPU_SUBTYPE_SH7706)
 #define SCI_ERI_IRQ    23
 #define SCI_RXI_IRQ    24
 #define SCI_TXI_IRQ    25
 #define SCIF0_IPR_POS  3
 #define SCIF0_PRIORITY 3
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7706) || \
       defined(CONFIG_CPU_SUBTYPE_SH7707) || \
       defined(CONFIG_CPU_SUBTYPE_SH7709)
 #define SCIF_ERI_IRQ   56
 #elif defined(CONFIG_CPU_SUBTYPE_SH7708)
 # define ONCHIP_NR_IRQS 32
 #elif defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7706) || \
       defined(CONFIG_CPU_SUBTYPE_SH7705)
 # define ONCHIP_NR_IRQS 64     // Actually 61
 # define PINT_NR_IRQS   16
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710)
+# define ONCHIP_NR_IRQS 104
 #elif defined(CONFIG_CPU_SUBTYPE_SH7750)
 # define ONCHIP_NR_IRQS 48     // Actually 44
 #elif defined(CONFIG_CPU_SUBTYPE_SH7751)
 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 # define ONCHIP_NR_IRQS 144
 #elif defined(CONFIG_CPU_SUBTYPE_SH7300) || \
-      defined(CONFIG_CPU_SUBTYPE_SH73180)
+      defined(CONFIG_CPU_SUBTYPE_SH73180) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7343)
 # define ONCHIP_NR_IRQS 109
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 # define ONCHIP_NR_IRQS 111
 # define OFFCHIP_NR_IRQS 4
 #elif defined(CONFIG_SH_R7780RP)
 # define OFFCHIP_NR_IRQS 16
+#elif defined(CONFIG_SH_7343_SOLUTION_ENGINE)
+# define OFFCHIP_NR_IRQS 12
 #elif defined(CONFIG_SH_UNKNOWN)
 # define OFFCHIP_NR_IRQS 16    /* Must also be last */
 #else
@@ -334,6 +341,11 @@ extern void enable_irq(unsigned int);
 extern void make_maskreg_irq(unsigned int irq);
 extern unsigned short *irq_mask_register;
 
+/*
+ * PINT IRQs
+ */
+void init_IRQ_pint(void);
+
 /*
  * Function for "on chip support modules".
  */
@@ -471,8 +483,10 @@ extern int ipr_irq_demux(int irq);
 
 #define INTC_ICR       0xfffffee0UL
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7706) || \
       defined(CONFIG_CPU_SUBTYPE_SH7707) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7709)
+      defined(CONFIG_CPU_SUBTYPE_SH7709) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7710)
 #define INTC_IRR0      0xa4000004UL
 #define INTC_IRR1      0xa4000006UL
 #define INTC_IRR2      0xa4000008UL
@@ -491,8 +505,105 @@ extern int ipr_irq_demux(int irq);
 #define INTC_IPRF      0xa4080000UL
 #define INTC_IPRG      0xa4080002UL
 #define INTC_IPRH      0xa4080004UL
-#endif
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710)
+/* Interrupt Controller Registers */
+#undef INTC_IPRA
+#undef INTC_IPRB
+#define INTC_IPRA      0xA414FEE2UL
+#define INTC_IPRB      0xA414FEE4UL
+#define INTC_IPRF      0xA4080000UL
+#define INTC_IPRG      0xA4080002UL
+#define INTC_IPRH      0xA4080004UL
+#define INTC_IPRI      0xA4080006UL
+
+#undef INTC_ICR0
+#undef INTC_ICR1
+#define INTC_ICR0      0xA414FEE0UL
+#define INTC_ICR1      0xA4140010UL
+
+#define INTC_IRR0      0xa4000004UL
+#define INTC_IRR1      0xa4000006UL
+#define INTC_IRR2      0xa4000008UL
+#define INTC_IRR3      0xa400000AUL
+#define INTC_IRR4      0xa400000CUL
+#define INTC_IRR5      0xa4080020UL
+#define INTC_IRR7      0xa4080024UL
+#define INTC_IRR8      0xa4080026UL
+
+/* Interrupt numbers */
+#define TIMER2_IRQ      18
+#define TIMER2_IPR_ADDR INTC_IPRA
+#define TIMER2_IPR_POS   1
+#define TIMER2_PRIORITY  2
+
+/* WDT */
+#define WDT_IRQ                27
+#define WDT_IPR_ADDR   INTC_IPRB
+#define WDT_IPR_POS     3
+#define WDT_PRIORITY    2
+
+#define SCIF0_ERI_IRQ  52
+#define SCIF0_RXI_IRQ  53
+#define SCIF0_BRI_IRQ  54
+#define SCIF0_TXI_IRQ  55
+#define SCIF0_IPR_ADDR INTC_IPRE
+#define SCIF0_IPR_POS  2
+#define SCIF0_PRIORITY 3
+
+#define DMTE4_IRQ      76
+#define DMTE5_IRQ      77
+#define DMA2_IPR_ADDR  INTC_IPRF
+#define DMA2_IPR_POS   2
+#define DMA2_PRIORITY  7
 
+#define IPSEC_IRQ      79
+#define IPSEC_IPR_ADDR INTC_IPRF
+#define IPSEC_IPR_POS  3
+#define IPSEC_PRIORITY 3
+
+/* EDMAC */
+#define EDMAC0_IRQ     80
+#define EDMAC0_IPR_ADDR        INTC_IPRG
+#define EDMAC0_IPR_POS 3
+#define EDMAC0_PRIORITY        3
+
+#define EDMAC1_IRQ     81
+#define EDMAC1_IPR_ADDR        INTC_IPRG
+#define EDMAC1_IPR_POS 2
+#define EDMAC1_PRIORITY        3
+
+#define EDMAC2_IRQ     82
+#define EDMAC2_IPR_ADDR        INTC_IPRG
+#define EDMAC2_IPR_POS 1
+#define EDMAC2_PRIORITY        3
+
+/* SIOF */
+#define SIOF0_ERI_IRQ  96
+#define SIOF0_TXI_IRQ  97
+#define SIOF0_RXI_IRQ  98
+#define SIOF0_CCI_IRQ  99
+#define SIOF0_IPR_ADDR INTC_IPRH
+#define SIOF0_IPR_POS  0
+#define SIOF0_PRIORITY 7
+
+#define SIOF1_ERI_IRQ  100
+#define SIOF1_TXI_IRQ  101
+#define SIOF1_RXI_IRQ  102
+#define SIOF1_CCI_IRQ  103
+#define SIOF1_IPR_ADDR INTC_IPRI
+#define SIOF1_IPR_POS  1
+#define SIOF1_PRIORITY 7
+#endif /* CONFIG_CPU_SUBTYPE_SH7710 */
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7710)
+#define PORT_PACR      0xa4050100UL
+#define PORT_PBCR      0xa4050102UL
+#define PORT_PCCR      0xa4050104UL
+#define PORT_PETCR     0xa4050106UL
+#define PORT_PADR      0xa4050120UL
+#define PORT_PBDR      0xa4050122UL
+#define PORT_PCDR      0xa4050124UL
+#else
 #define PORT_PACR      0xa4000100UL
 #define PORT_PBCR      0xa4000102UL
 #define PORT_PCCR      0xa4000104UL
@@ -501,6 +612,7 @@ extern int ipr_irq_demux(int irq);
 #define PORT_PBDR      0xa4000122UL
 #define PORT_PCDR      0xa4000124UL
 #define PORT_PFDR      0xa400012aUL
+#endif
 
 #define IRQ0_IRQ       32
 #define IRQ1_IRQ       33
@@ -577,7 +689,7 @@ extern int ipr_irq_demux(int irq);
 #define NR_INTC2_IRQS  64
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define INTC2_BASE     0xffd40000
-#define INTC2_FIRST_IRQ        22
+#define INTC2_FIRST_IRQ        21
 #define INTC2_INTMSK_OFFSET    (0x38)
 #define INTC2_INTMSKCLR_OFFSET (0x3c)
 #define NR_INTC2_IRQS  60
@@ -594,6 +706,8 @@ void intc2_add_clear_irq(int irq, int (*fn)(int));
 
 #endif
 
+extern int shmse_irq_demux(int irq);
+
 static inline int generic_irq_demux(int irq)
 {
        return irq;
@@ -605,8 +719,21 @@ static inline int generic_irq_demux(int irq)
 #define irq_canonicalize(irq)  (irq)
 #define irq_demux(irq)         __irq_demux(sh_mv.mv_irq_demux(irq))
 
+#ifdef CONFIG_4KSTACKS
+extern void irq_ctx_init(int cpu);
+extern void irq_ctx_exit(int cpu);
+# define __ARCH_HAS_DO_SOFTIRQ
+#else
+# define irq_ctx_init(cpu) do { } while (0)
+# define irq_ctx_exit(cpu) do { } while (0)
+#endif
+
 #if defined(CONFIG_CPU_SUBTYPE_SH73180)
 #include <asm/irq-sh73180.h>
 #endif
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7343)
+#include <asm/irq-sh7343.h>
+#endif
+
 #endif /* __ASM_SH_IRQ_H */
index 9dfe59f6fcb5c01a6ac2bc20ef6da871c31c04c9..9d235af20cdd551136beefd6968e72e4984c0f5b 100644 (file)
 /* The native architecture */
 #define KEXEC_ARCH KEXEC_ARCH_SH
 
-#ifndef __ASSEMBLY__
+#define MAX_NOTE_BYTES 1024
 
-extern void machine_shutdown(void);
-extern void *crash_notes;
-
-#endif /* __ASSEMBLY__ */
+/* Provide a dummy definition to avoid build failures. */
+static inline void crash_setup_regs(struct pt_regs *newregs,
+                                       struct pt_regs *oldregs) { }
 
 #endif /* _SH_KEXEC_H */
index 1653ffb75fbe75f857aebee1ad645b69f1d45446..7b26f53fe343f5711f97bbecdec0dd563be36ba6 100644 (file)
@@ -128,4 +128,19 @@ extern int     setjmp(jmp_buf __jmpb);
 #define KGDB_ASSERT(condition, message)
 #endif
 
+/* Taken from sh-stub.c of GDB 4.18 */
+static const char hexchars[] = "0123456789abcdef";
+
+/* Get high hex bits */
+static inline char highhex(const int x)
+{
+       return hexchars[(x >> 4) & 0xf];
+}
+
+/* Get low hex bits */
+static inline char lowhex(const int x)
+{
+       return hexchars[x & 0xf];
+}
+
 #endif
diff --git a/include/asm-sh/landisk/gio.h b/include/asm-sh/landisk/gio.h
new file mode 100644 (file)
index 0000000..3fce4c4
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __ASM_SH_LANDISK_GIO_H
+#define __ASM_SH_LANDISK_GIO_H
+
+#include <linux/ioctl.h>
+
+/* version */
+#define VERSION_STR    "1.00"
+
+/* Driver name */
+#define GIO_DRIVER_NAME                "/dev/giodrv"
+
+/* Use 'k' as magic number */
+#define GIODRV_IOC_MAGIC  'k'
+
+#define GIODRV_IOCRESET    _IO(GIODRV_IOC_MAGIC, 0)
+/*
+ * S means "Set" through a ptr,
+ * T means "Tell" directly
+ * G means "Get" (to a pointed var)
+ * Q means "Query", response is on the return value
+ * X means "eXchange": G and S atomically
+ * H means "sHift": T and Q atomically
+ */
+#define GIODRV_IOCSGIODATA1   _IOW(GIODRV_IOC_MAGIC,  1, unsigned char *)
+#define GIODRV_IOCGGIODATA1   _IOR(GIODRV_IOC_MAGIC,  2, unsigned char *)
+#define GIODRV_IOCSGIODATA2   _IOW(GIODRV_IOC_MAGIC,  3, unsigned short *)
+#define GIODRV_IOCGGIODATA2   _IOR(GIODRV_IOC_MAGIC,  4, unsigned short *)
+#define GIODRV_IOCSGIODATA4   _IOW(GIODRV_IOC_MAGIC,  5, unsigned long *)
+#define GIODRV_IOCGGIODATA4   _IOR(GIODRV_IOC_MAGIC,  6, unsigned long *)
+#define GIODRV_IOCSGIOSETADDR _IOW(GIODRV_IOC_MAGIC,  7, unsigned long *)
+#define GIODRV_IOCHARDRESET   _IO(GIODRV_IOC_MAGIC, 8) /* debugging tool */
+
+#define GIODRV_IOCSGIO_LED    _IOW(GIODRV_IOC_MAGIC,  9, unsigned long *)
+#define GIODRV_IOCGGIO_LED    _IOR(GIODRV_IOC_MAGIC,  10, unsigned long *)
+#define GIODRV_IOCSGIO_BUZZER _IOW(GIODRV_IOC_MAGIC,  11, unsigned long *)
+#define GIODRV_IOCGGIO_LANDISK _IOR(GIODRV_IOC_MAGIC,  14, unsigned long *)
+#define GIODRV_IOCGGIO_BTN _IOR(GIODRV_IOC_MAGIC,  22, unsigned long *)
+#define GIODRV_IOCSGIO_BTNPID _IOW(GIODRV_IOC_MAGIC,  23, unsigned long *)
+#define GIODRV_IOCGGIO_BTNPID _IOR(GIODRV_IOC_MAGIC,  24, unsigned long *)
+
+#define GIODRV_IOC_MAXNR 8
+#define GIO_READ 0x00000000
+#define GIO_WRITE 0x00000001
+
+#endif /* __ASM_SH_LANDISK_GIO_H  */
diff --git a/include/asm-sh/landisk/ide.h b/include/asm-sh/landisk/ide.h
new file mode 100644 (file)
index 0000000..6490e28
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * modifed by kogiidena
+ * 2005.03.03
+ */
+
+#ifndef __ASM_SH_LANDISK_IDE_H
+#define __ASM_SH_LANDISK_IDE_H
+
+/* Nothing to see here.. */
+#include <asm/landisk/iodata_landisk.h>
+#define IRQ_CFCARD     IRQ_FATA        /* CF Card IRQ */
+#define IRQ_PCMCIA     IRQ_ATA         /* PCMCIA IRQ */
+
+#endif /* __ASM_SH_LANDISK_IDE_H  */
diff --git a/include/asm-sh/landisk/iodata_landisk.h b/include/asm-sh/landisk/iodata_landisk.h
new file mode 100644 (file)
index 0000000..c74d3c7
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef __ASM_SH_IODATA_LANDISK_H
+#define __ASM_SH_IODATA_LANDISK_H
+
+/*
+ * linux/include/asm-sh/landisk/iodata_landisk.h
+ *
+ * Copyright (C) 2000  Atom Create Engineering Co., Ltd.
+ *
+ * IO-DATA LANDISK support
+ */
+
+/* Box specific addresses.  */
+
+#define PA_USB         0xa4000000      /* USB Controller M66590 */
+
+#define PA_ATARST      0xb0000000      /* ATA/FATA Access Control Register */
+#define PA_LED         0xb0000001      /* LED Control Register */
+#define PA_STATUS      0xb0000002      /* Switch Status Register */
+#define PA_SHUTDOWN    0xb0000003      /* Shutdown Control Register */
+#define PA_PCIPME      0xb0000004      /* PCI PME Status Register */
+#define PA_IMASK       0xb0000005      /* Interrupt Mask Register */
+/* 2003.10.31 I-O DATA NSD NWG add.    for shutdown port clear */
+#define PA_PWRINT_CLR  0xb0000006      /* Shutdown Interrupt clear Register */
+
+#define PA_LCD_CLRDSP  0x00            /* LCD Clear Display Offset */
+#define PA_LCD_RTNHOME 0x00            /* LCD Return Home Offset */
+#define PA_LCD_ENTMODE 0x00            /* LCD Entry Mode Offset */
+#define PA_LCD_DSPCTL  0x00            /* LCD Display ON/OFF Control Offset */
+#define PA_LCD_FUNC    0x00            /* LCD Function Set Offset */
+#define PA_LCD_CGRAM   0x00            /* LCD Set CGRAM Address Offset */
+#define PA_LCD_DDRAM   0x00            /* LCD Set DDRAM Address Offset */
+#define PA_LCD_RDFLAG  0x01            /* LCD Read Busy Flag Offset */
+#define PA_LCD_WTDATA  0x02            /* LCD Write Datat to RAM Offset */
+#define PA_LCD_RDDATA  0x03            /* LCD Read Data from RAM Offset */
+#define PA_PIDE_OFFSET 0x40            /* CF IDE Offset */
+#define PA_SIDE_OFFSET 0x40            /* HDD IDE Offset */
+
+#define IRQ_PCIINTA    5               /* PCI INTA IRQ */
+#define IRQ_PCIINTB    6               /* PCI INTB IRQ */
+#define IRQ_PCIINDC    7               /* PCI INTC IRQ */
+#define IRQ_PCIINTD    8               /* PCI INTD IRQ */
+#define IRQ_ATA                9               /* ATA IRQ */
+#define IRQ_FATA       10              /* FATA IRQ */
+#define IRQ_POWER      11              /* Power Switch IRQ */
+#define IRQ_BUTTON     12              /* USL-5P Button IRQ */
+#define IRQ_FAULT      13              /* USL-5P Fault  IRQ */
+
+#define SHUTDOWN_BTN_MAJOR     99      /* Shutdown button device major no. */
+
+#define SHUTDOWN_LOOP_CNT      5       /* Shutdown button Detection loop */
+#define SHUTDOWN_DELAY         200     /* Shutdown button delay value(ms) */
+
+
+/* added by kogiidena */
+/*
+ *  landisk_ledparam
+ *
+ * led  ------10 -6543210 -6543210 -6543210
+ *     |000000..|0.......|0.......|U.......|
+ *     |  HARD  |fastblik| blink  |   on   |
+ *
+ *   led0: power       U:update flag
+ *   led1: error
+ *   led2: usb1
+ *   led3: usb2
+ *   led4: usb3
+ *   led5: usb4
+ *   led6: usb5
+ *
+ */
+extern int landisk_ledparam;    /* from setup.c */
+extern int landisk_buzzerparam; /* from setup.c */
+extern int landisk_arch;        /* from setup.c */
+
+#define __IO_PREFIX landisk
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_IODATA_LANDISK_H */
+
index 550501fa4fede12048f4a288e6880fc9311bab78..70389b72ffef9dce063f55f576aa01fa2c40bdee 100644 (file)
@@ -8,17 +8,18 @@
  */
 
 #ifndef _ASM_SH_MACHVEC_H
-#define _ASM_SH_MACHVEC_H 1
+#define _ASM_SH_MACHVEC_H
 
 #include <linux/types.h>
 #include <linux/time.h>
-
 #include <asm/machtypes.h>
 #include <asm/machvec_init.h>
 
 struct device;
 
 struct sh_machine_vector {
+       void (*mv_setup)(char **cmdline_p);
+       const char *mv_name;
        int mv_nr_irqs;
 
        u8 (*mv_inb)(unsigned long);
@@ -65,4 +66,6 @@ struct sh_machine_vector {
 
 extern struct sh_machine_vector sh_mv;
 
+#define get_system_type()      sh_mv.mv_name
+
 #endif /* _ASM_SH_MACHVEC_H */
index 1707cfb2915d04fcccf357035689881ef71d2133..0aee96a973304d0a816100b750ceda899005505f 100644 (file)
@@ -4,173 +4,4 @@
 #ifndef _ASM_MC146818RTC_H
 #define _ASM_MC146818RTC_H
 
-#ifdef CONFIG_SH_MPC1211
-#undef  _ASM_MC146818RTC_H
-#undef  RTC_IRQ
-#include <asm/mpc1211/mc146818rtc.h>
-#else
-
-#include <asm/rtc.h>
-
-#define RTC_ALWAYS_BCD 1
-
-/* FIXME:RTC Interrupt feature is not implemented yet. */
-#undef  RTC_IRQ
-#define RTC_IRQ                0
-
-#if defined(CONFIG_CPU_SH3)
-#define RTC_PORT(n)            (R64CNT+(n)*2)
-#define CMOS_READ(addr)                __CMOS_READ(addr,b)
-#define CMOS_WRITE(val,addr)   __CMOS_WRITE(val,addr,b)
-
-#elif defined(CONFIG_SH_SECUREEDGE5410)
-#include <asm/snapgear/io.h>
-
-#define RTC_PORT(n)             SECUREEDGE_IOPORT_ADDR
-#define CMOS_READ(addr)         secureedge5410_cmos_read(addr)
-#define CMOS_WRITE(val,addr)    secureedge5410_cmos_write(val,addr)
-extern unsigned char secureedge5410_cmos_read(int addr);
-extern void secureedge5410_cmos_write(unsigned char val, int addr);
-
-#elif defined(CONFIG_CPU_SH4)
-#define RTC_PORT(n)            (R64CNT+(n)*4)
-#define CMOS_READ(addr)                __CMOS_READ(addr,w)
-#define CMOS_WRITE(val,addr)   __CMOS_WRITE(val,addr,w)
-#endif
-
-#define __CMOS_READ(addr, s) ({                                                \
-       unsigned char val=0, rcr1, rcr2, r64cnt, retry;                 \
-       switch(addr) {                                                  \
-               case RTC_SECONDS:                                       \
-                       val = ctrl_inb(RSECCNT);                        \
-                       break;                                          \
-               case RTC_SECONDS_ALARM:                                 \
-                       val = ctrl_inb(RSECAR);                         \
-                       break;                                          \
-               case RTC_MINUTES:                                       \
-                       val = ctrl_inb(RMINCNT);                        \
-                       break;                                          \
-               case RTC_MINUTES_ALARM:                                 \
-                       val = ctrl_inb(RMINAR);                         \
-                       break;                                          \
-               case RTC_HOURS:                                         \
-                       val = ctrl_inb(RHRCNT);                         \
-                       break;                                          \
-               case RTC_HOURS_ALARM:                                   \
-                       val = ctrl_inb(RHRAR);                          \
-                       break;                                          \
-               case RTC_DAY_OF_WEEK:                                   \
-                       val = ctrl_inb(RWKCNT);                         \
-                       break;                                          \
-               case RTC_DAY_OF_MONTH:                                  \
-                       val = ctrl_inb(RDAYCNT);                        \
-                       break;                                          \
-               case RTC_MONTH:                                         \
-                       val = ctrl_inb(RMONCNT);                        \
-                       break;                                          \
-               case RTC_YEAR:                                          \
-                       val = ctrl_in##s(RYRCNT);                       \
-                       break;                                          \
-               case RTC_REG_A: /* RTC_FREQ_SELECT */                   \
-                       rcr2 = ctrl_inb(RCR2);                          \
-                       val = (rcr2 & RCR2_PESMASK) >> 4;               \
-                       rcr1 = ctrl_inb(RCR1);                          \
-                       rcr1 = (rcr1 & (RCR1_CIE | RCR1_AIE)) | RCR1_AF;\
-                       retry = 0;                                      \
-                       do {                                            \
-                               ctrl_outb(rcr1, RCR1); /* clear CF */   \
-                               r64cnt = ctrl_inb(R64CNT);              \
-                       } while((ctrl_inb(RCR1) & RCR1_CF) && retry++ < 1000);\
-                       r64cnt ^= RTC_BIT_INVERTED;                     \
-                       if(r64cnt == 0x7f || r64cnt == 0)               \
-                               val |= RTC_UIP;                         \
-                       break;                                          \
-               case RTC_REG_B: /* RTC_CONTROL */                       \
-                       rcr1 = ctrl_inb(RCR1);                          \
-                       rcr2 = ctrl_inb(RCR2);                          \
-                       if(rcr1 & RCR1_CIE)     val |= RTC_UIE;         \
-                       if(rcr1 & RCR1_AIE)     val |= RTC_AIE;         \
-                       if(rcr2 & RCR2_PESMASK) val |= RTC_PIE;         \
-                       if(!(rcr2 & RCR2_START))val |= RTC_SET;         \
-                       val |= RTC_24H;                                 \
-                       break;                                          \
-               case RTC_REG_C: /* RTC_INTR_FLAGS */                    \
-                       rcr1 = ctrl_inb(RCR1);                          \
-                       rcr1 &= ~(RCR1_CF | RCR1_AF);                   \
-                       ctrl_outb(rcr1, RCR1);                          \
-                       rcr2 = ctrl_inb(RCR2);                          \
-                       rcr2 &= ~RCR2_PEF;                              \
-                       ctrl_outb(rcr2, RCR2);                          \
-                       break;                                          \
-               case RTC_REG_D: /* RTC_VALID */                         \
-                       /* Always valid ... */                          \
-                       val = RTC_VRT;                                  \
-                       break;                                          \
-               default:                                                \
-                       break;                                          \
-       }                                                               \
-       val;                                                            \
-})
-
-#define __CMOS_WRITE(val, addr, s) ({                                  \
-       unsigned char rcr1,rcr2;                                        \
-       switch(addr) {                                                  \
-               case RTC_SECONDS:                                       \
-                       ctrl_outb(val, RSECCNT);                        \
-                       break;                                          \
-               case RTC_SECONDS_ALARM:                                 \
-                       ctrl_outb(val, RSECAR);                         \
-                       break;                                          \
-               case RTC_MINUTES:                                       \
-                       ctrl_outb(val, RMINCNT);                        \
-                       break;                                          \
-               case RTC_MINUTES_ALARM:                                 \
-                       ctrl_outb(val, RMINAR);                         \
-                       break;                                          \
-               case RTC_HOURS:                                         \
-                       ctrl_outb(val, RHRCNT);                         \
-                       break;                                          \
-               case RTC_HOURS_ALARM:                                   \
-                       ctrl_outb(val, RHRAR);                          \
-                       break;                                          \
-               case RTC_DAY_OF_WEEK:                                   \
-                       ctrl_outb(val, RWKCNT);                         \
-                       break;                                          \
-               case RTC_DAY_OF_MONTH:                                  \
-                       ctrl_outb(val, RDAYCNT);                        \
-                       break;                                          \
-               case RTC_MONTH:                                         \
-                       ctrl_outb(val, RMONCNT);                        \
-                       break;                                          \
-               case RTC_YEAR:                                          \
-                       ctrl_out##s((ctrl_in##s(RYRCNT) & 0xff00) | (val & 0xff), RYRCNT);\
-                       break;                                          \
-               case RTC_REG_A: /* RTC_FREQ_SELECT */                   \
-                       rcr2 = ctrl_inb(RCR2);                          \
-                       if((val & RTC_DIV_CTL) == RTC_DIV_RESET2)       \
-                               rcr2 |= RCR2_RESET;                     \
-                       ctrl_outb(rcr2, RCR2);                          \
-                       break;                                          \
-               case RTC_REG_B: /* RTC_CONTROL */                       \
-                       rcr1 = (ctrl_inb(RCR1) & 0x99) | RCR1_AF;       \
-                       if(val & RTC_AIE) rcr1 |= RCR1_AIE;             \
-                       else              rcr1 &= ~RCR1_AIE;            \
-                       if(val & RTC_UIE) rcr1 |= RCR1_CIE;             \
-                       else              rcr1 &= ~RCR1_CIE;            \
-                       ctrl_outb(rcr1, RCR1);                          \
-                       rcr2 = ctrl_inb(RCR2);                          \
-                       if(val & RTC_SET) rcr2 &= ~RCR2_START;          \
-                       else              rcr2 |= RCR2_START;           \
-                       ctrl_outb(rcr2, RCR2);                          \
-                       break;                                          \
-               case RTC_REG_C: /* RTC_INTR_FLAGS */                    \
-                       break;                                          \
-               case RTC_REG_D: /* RTC_VALID */                         \
-                       break;                                          \
-               default:                                                \
-                       break;                                          \
-       }                                                               \
-})
-
-#endif /* CONFIG_SH_MPC1211 */
 #endif /* _ASM_MC146818RTC_H */
index 72f07be6117fa23bbaaeb91d9c8e8a882fbaa57e..cf47df79bb9415c43a310c16c3c93737ebc2c1d2 100644 (file)
@@ -3,27 +3,76 @@
 
 #if !defined(CONFIG_MMU)
 
-struct mm_rblock_struct {
-       int     size;
-       int     refcount;
-       void    *kblock;
-};
-
-struct mm_tblock_struct {
-       struct mm_rblock_struct *rblock;
-       struct mm_tblock_struct *next;
-};
-
 typedef struct {
-       struct mm_tblock_struct tblock;
+       struct vm_list_struct   *vmlist;
        unsigned long           end_brk;
 } mm_context_t;
 
 #else
 
 /* Default "unsigned long" context */
-typedef unsigned long mm_context_t;
+typedef unsigned long mm_context_id_t;
+
+typedef struct {
+       mm_context_id_t id;
+       void *vdso;
+} mm_context_t;
 
 #endif /* CONFIG_MMU */
-#endif /* __MMH_H */
+
+/*
+ * Privileged Space Mapping Buffer (PMB) definitions
+ */
+#define PMB_PASCR              0xff000070
+#define PMB_IRMCR              0xff000078
+
+#define PMB_ADDR               0xf6100000
+#define PMB_DATA               0xf7100000
+#define PMB_ENTRY_MAX          16
+#define PMB_E_MASK             0x0000000f
+#define PMB_E_SHIFT            8
+
+#define PMB_SZ_16M             0x00000000
+#define PMB_SZ_64M             0x00000010
+#define PMB_SZ_128M            0x00000080
+#define PMB_SZ_512M            0x00000090
+#define PMB_SZ_MASK            PMB_SZ_512M
+#define PMB_C                  0x00000008
+#define PMB_WT                 0x00000001
+#define PMB_UB                 0x00000200
+#define PMB_V                  0x00000100
+
+#define PMB_NO_ENTRY           (-1)
+
+struct pmb_entry;
+
+struct pmb_entry {
+       unsigned long vpn;
+       unsigned long ppn;
+       unsigned long flags;
+
+       /*
+        * 0 .. NR_PMB_ENTRIES for specific entry selection, or
+        * PMB_NO_ENTRY to search for a free one
+        */
+       int entry;
+
+       struct pmb_entry *next;
+       /* Adjacent entry link for contiguous multi-entry mappings */
+       struct pmb_entry *link;
+};
+
+/* arch/sh/mm/pmb.c */
+int __set_pmb_entry(unsigned long vpn, unsigned long ppn,
+                   unsigned long flags, int *entry);
+int set_pmb_entry(struct pmb_entry *pmbe);
+void clear_pmb_entry(struct pmb_entry *pmbe);
+struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
+                           unsigned long flags);
+void pmb_free(struct pmb_entry *pmbe);
+long pmb_remap(unsigned long virt, unsigned long phys,
+              unsigned long size, unsigned long flags);
+void pmb_unmap(unsigned long addr);
+
+#endif /* __MMU_H */
 
index 6760d064bd0233bfca2ac5217a5e42cf9b113283..c7088efe579add81dae62e2a3dd54134b06fef3b 100644 (file)
@@ -49,7 +49,7 @@ get_mmu_context(struct mm_struct *mm)
        unsigned long mc = mmu_context_cache;
 
        /* Check if we have old version of context. */
-       if (((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)
+       if (((mm->context.id ^ mc) & MMU_CONTEXT_VERSION_MASK) == 0)
                /* It's up to date, do nothing */
                return;
 
@@ -68,7 +68,7 @@ get_mmu_context(struct mm_struct *mm)
                if (!mc)
                        mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION;
        }
-       mm->context = mc;
+       mm->context.id = mc;
 }
 
 /*
@@ -78,7 +78,7 @@ get_mmu_context(struct mm_struct *mm)
 static __inline__ int init_new_context(struct task_struct *tsk,
                                       struct mm_struct *mm)
 {
-       mm->context = NO_CONTEXT;
+       mm->context.id = NO_CONTEXT;
 
        return 0;
 }
@@ -123,7 +123,7 @@ static __inline__ unsigned long get_asid(void)
 static __inline__ void activate_context(struct mm_struct *mm)
 {
        get_mmu_context(mm);
-       set_asid(mm->context & MMU_CONTEXT_ASID_MASK);
+       set_asid(mm->context.id & MMU_CONTEXT_ASID_MASK);
 }
 
 /* MMU_TTB can be used for optimizing the fault handling.
@@ -174,9 +174,7 @@ static inline void enable_mmu(void)
 {
        /* Enable MMU */
        ctrl_outl(MMU_CONTROL_INIT, MMUCR);
-
-       /* The manual suggests doing some nops after turning on the MMU */
-       __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop\n\t");
+       ctrl_barrier();
 
        if (mmu_context_cache == NO_CONTEXT)
                mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;
@@ -191,7 +189,8 @@ static inline void disable_mmu(void)
        cr = ctrl_inl(MMUCR);
        cr &= ~MMU_CONTROL_INIT;
        ctrl_outl(cr, MMUCR);
-       __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop\n\t");
+
+       ctrl_barrier();
 }
 #else
 /*
diff --git a/include/asm-sh/overdrive/fpga.h b/include/asm-sh/overdrive/fpga.h
deleted file mode 100644 (file)
index 1cd8799..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- */
-
-#ifndef __FPGA_OD_H__
-#define __FPGA_OD_H__
-
-/* This routine will program up the fpga which interfaces to the galileo */
-int init_overdrive_fpga(void);
-
-#endif
diff --git a/include/asm-sh/overdrive/gt64111.h b/include/asm-sh/overdrive/gt64111.h
deleted file mode 100644 (file)
index 01d58bc..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-#ifndef _GT64111_H_
-#define _GT64111_H_
-
-#define MASTER_INTERFACE         0x0
-#define RAS10_LO_DEC_ADR         0x8        
-#define RAS10_HI_DEC_ADR         0x10
-#define RAS32_LO_DEC_ADR         0x18
-#define RAS32_HI_DEC_ADR         0x20
-#define CS20_LO_DEC_ADR          0x28
-#define CS20_HI_DEC_ADR          0x30
-#define CS3_LO_DEC_ADR           0x38
-#define CS3_HI_DEC_ADR           0x40
-#define PCI_IO_LO_DEC_ADR        0x48
-#define PCI_IO_HI_DEC_ADR        0x50
-#define PCI_MEM0_LO_DEC_ADR      0x58
-#define PCI_MEM0_HI_DEC_ADR      0x60
-#define INTERNAL_SPACE_DEC       0x68
-#define BUS_ERR_ADR_LO_CPU       0x70
-#define READONLY0                0x78
-#define PCI_MEM1_LO_DEC_ADR      0x80
-#define PCI_MEM1_HI_DEC_ADR      0x88
-#define RAS0_LO_DEC_ADR          0x400   
-#define RAS0_HI_DEC_ADR          0x404
-#define RAS1_LO_DEC_ADR          0x408
-#define RAS1_HI_DEC_ADR          0x40c
-#define RAS2_LO_DEC_ADR          0x410
-#define RAS2_HI_DEC_ADR          0x414
-#define RAS3_LO_DEC_ADR          0x418
-#define RAS3_HI_DEC_ADR          0x41c
-#define DEV_CS0_LO_DEC_ADR       0x420
-#define DEV_CS0_HI_DEC_ADR       0x424
-#define DEV_CS1_LO_DEC_ADR       0x428
-#define DEV_CS1_HI_DEC_ADR       0x42c
-#define DEV_CS2_LO_DEC_ADR       0x430
-#define DEV_CS2_HI_DEC_ADR       0x434
-#define DEV_CS3_LO_DEC_ADR       0x438
-#define DEV_CS3_HI_DEC_ADR       0x43c
-#define DEV_BOOTCS_LO_DEC_ADR    0x440
-#define DEV_BOOTCS_HI_DEC_ADR    0x444
-#define DEV_ADR_DEC_ERR          0x470
-#define DRAM_CFG                 0x448   
-#define DRAM_BANK0_PARMS         0x44c   
-#define DRAM_BANK1_PARMS         0x450
-#define DRAM_BANK2_PARMS         0x454
-#define DRAM_BANK3_PARMS         0x458
-#define DEV_BANK0_PARMS          0x45c
-#define DEV_BANK1_PARMS          0x460
-#define DEV_BANK2_PARMS          0x464
-#define DEV_BANK3_PARMS          0x468
-#define DEV_BOOT_BANK_PARMS      0x46c
-#define CH0_DMA_BYTECOUNT        0x800
-#define CH1_DMA_BYTECOUNT        0x804
-#define CH2_DMA_BYTECOUNT        0x808
-#define CH3_DMA_BYTECOUNT        0x80c
-#define CH0_DMA_SRC_ADR          0x810
-#define CH1_DMA_SRC_ADR          0x814
-#define CH2_DMA_SRC_ADR          0x818
-#define CH3_DMA_SRC_ADR          0x81c
-#define CH0_DMA_DST_ADR          0x820
-#define CH1_DMA_DST_ADR          0x824
-#define CH2_DMA_DST_ADR          0x828
-#define CH3_DMA_DST_ADR          0x82c
-#define CH0_NEXT_REC_PTR         0x830
-#define CH1_NEXT_REC_PTR         0x834
-#define CH2_NEXT_REC_PTR         0x838
-#define CH3_NEXT_REC_PTR         0x83c
-#define CH0_CTRL                 0x840
-#define CH1_CTRL                 0x844
-#define CH2_CTRL                 0x848
-#define CH3_CTRL                 0x84c
-#define DMA_ARBITER              0x860
-#define TIMER0                   0x850
-#define TIMER1                   0x854
-#define TIMER2                   0x858
-#define TIMER3                   0x85c
-#define TIMER_CTRL               0x864
-#define PCI_CMD                  0xc00
-#define PCI_TIMEOUT              0xc04
-#define PCI_RAS10_BANK_SIZE      0xc08
-#define PCI_RAS32_BANK_SIZE      0xc0c
-#define PCI_CS20_BANK_SIZE       0xc10
-#define PCI_CS3_BANK_SIZE        0xc14
-#define PCI_SERRMASK             0xc28
-#define PCI_INTACK               0xc34
-#define PCI_BAR_EN               0xc3c
-#define PCI_CFG_ADR              0xcf8
-#define PCI_CFG_DATA             0xcfc
-#define PCI_INTCAUSE             0xc18
-#define PCI_MAST_MASK            0xc1c
-#define PCI_PCIMASK              0xc24
-#define BAR_ENABLE_ADR           0xc3c
-
-/* These are config registers, accessible via PCI space */
-#define PCI_CONFIG_RAS10_BASE_ADR   0x010
-#define PCI_CONFIG_RAS32_BASE_ADR   0x014
-#define PCI_CONFIG_CS20_BASE_ADR    0x018
-#define PCI_CONFIG_CS3_BASE_ADR     0x01c
-#define PCI_CONFIG_INT_REG_MM_ADR   0x020
-#define PCI_CONFIG_INT_REG_IO_ADR   0x024
-#define PCI_CONFIG_BOARD_VENDOR     0x02c
-#define PCI_CONFIG_ROM_ADR          0x030
-#define PCI_CONFIG_INT_PIN_LINE     0x03c
-
-
-
-
-
-#endif
-
diff --git a/include/asm-sh/overdrive/io.h b/include/asm-sh/overdrive/io.h
deleted file mode 100644 (file)
index 0dba700..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * include/asm-sh/io_od.h
- *
- * 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 an STMicroelectronics Overdrive
- */
-
-#ifndef _ASM_SH_IO_OD_H
-#define _ASM_SH_IO_OD_H
-
-extern unsigned char od_inb(unsigned long port);
-extern unsigned short od_inw(unsigned long port);
-extern unsigned int od_inl(unsigned long port);
-
-extern void od_outb(unsigned char value, unsigned long port);
-extern void od_outw(unsigned short value, unsigned long port);
-extern void od_outl(unsigned int value, unsigned long port);
-
-extern unsigned char od_inb_p(unsigned long port);
-extern unsigned short od_inw_p(unsigned long port);
-extern unsigned int od_inl_p(unsigned long port);
-extern void od_outb_p(unsigned char value, unsigned long port);
-extern void od_outw_p(unsigned short value, unsigned long port);
-extern void od_outl_p(unsigned int value, unsigned long port);
-
-extern void od_insb(unsigned long port, void *addr, unsigned long count);
-extern void od_insw(unsigned long port, void *addr, unsigned long count);
-extern void od_insl(unsigned long port, void *addr, unsigned long count);
-extern void od_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void od_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void od_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned long od_isa_port2addr(unsigned long offset);
-
-#endif /* _ASM_SH_IO_OD_H */
diff --git a/include/asm-sh/overdrive/overdrive.h b/include/asm-sh/overdrive/overdrive.h
deleted file mode 100644 (file)
index fc746c2..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/* 
- * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.                            
- *
- */
-
-
-#ifndef __OVERDRIVE_H__
-#define __OVERDRIVE_H__
-
-#define OVERDRIVE_INT_CT 0xa3a00000
-#define OVERDRIVE_INT_DT 0xa3b00000
-
-#define OVERDRIVE_CTRL    0xa3000000
-
-/* Shoving all these bits into the same register is not a good idea. 
- * As soon as I get a spare moment, I'll change the FPGA and put each 
- * bit in a separate register
- */
-
-#define VALID_CTRL_BITS                          0x1f
-
-#define ENABLE_RS232_MASK                0x1e
-#define DISABLE_RS232_BIT                0x01
-
-#define ENABLE_NMI_MASK                          0x1d
-#define DISABLE_NMI_BIT                          0x02
-
-#define RESET_PCI_MASK                   0x1b
-#define ENABLE_PCI_BIT                   0x04
-
-#define ENABLE_LED_MASK                          0x17
-#define DISABLE_LED_BIT                          0x08
-
-#define RESET_FPGA_MASK                          0x0f
-#define ENABLE_FPGA_BIT                          0x10
-
-
-#define FPGA_DCLK_ADDRESS           0xA3C00000
-
-#define FPGA_DATA        0x01  /*   W */
-#define FPGA_CONFDONE    0x02  /* R   */
-#define FPGA_NOT_STATUS  0x04  /* R   */
-#define FPGA_INITDONE    0x08  /* R   */
-
-#define FPGA_TIMEOUT     100000
-
-
-/* Interrupts for the overdrive. Note that these numbers have 
- * nothing to do with the actual IRQ numbers they appear on, 
- * this is all programmable. This is simply the position in the 
- * INT_CT register.
- */
-
-#define OVERDRIVE_PCI_INTA              0
-#define OVERDRIVE_PCI_INTB              1
-#define OVERDRIVE_PCI_INTC              2
-#define OVERDRIVE_PCI_INTD              3
-#define OVERDRIVE_GALILEO_INT           4
-#define OVERDRIVE_GALILEO_LOCAL_INT     5
-#define OVERDRIVE_AUDIO_INT             6
-#define OVERDRIVE_KEYBOARD_INT          7
-
-/* Which Linux IRQ should we assign to each interrupt source? */
-#define OVERDRIVE_PCI_IRQ1              2
-#ifdef CONFIG_HACKED_NE2K
-#define OVERDRIVE_PCI_IRQ2              7
-#else
-#define OVERDRIVE_PCI_IRQ2              2
-#undef OVERDRIVE_PCI_INTB 
-#define OVERDRIVE_PCI_INTB OVERDRIVE_PCI_INTA
-
-#endif
-
-/* Put the ESS solo audio chip on IRQ 4 */
-#define OVERDRIVE_ESS_IRQ               4
-
-/* Where the memory behind the PCI bus appears */
-#define PCI_DRAM_BASE   0xb7000000
-#define PCI_DRAM_SIZE (16*1024*1024)
-#define PCI_DRAM_FINISH (PCI_DRAM_BASE+PCI_DRAM_SIZE-1)
-
-/* Where the IO region appears in the memory */
-#define PCI_GTIO_BASE   0xb8000000
-
-#endif
index 6f7eb8a3aba53203c57d697c0aaca70185855304..ca8b26d90475937f0d80dde07cd2b2c12e44127c 100644 (file)
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT     12
+
+#ifdef __ASSEMBLY__
+#define PAGE_SIZE      (1 << PAGE_SHIFT)
+#else
 #define PAGE_SIZE      (1UL << PAGE_SHIFT)
+#endif
+
 #define PAGE_MASK      (~(PAGE_SIZE-1))
 #define PTE_MASK       PAGE_MASK
 
@@ -30,7 +36,6 @@
 #define HPAGE_SIZE             (1UL << HPAGE_SHIFT)
 #define HPAGE_MASK             (~(HPAGE_SIZE-1))
 #define HUGETLB_PAGE_ORDER     (HPAGE_SHIFT-PAGE_SHIFT)
-#define ARCH_HAS_SETCLEAR_HUGE_PTE
 #endif
 
 #ifdef __KERNEL__
 extern void (*clear_page)(void *to);
 extern void (*copy_page)(void *to, void *from);
 
+extern unsigned long shm_align_mask;
+
+#ifdef CONFIG_MMU
 extern void clear_page_slow(void *to);
 extern void copy_page_slow(void *to, void *from);
+#else
+extern void clear_page_nommu(void *to);
+extern void copy_page_nommu(void *to, void *from);
+#endif
 
-#if defined(CONFIG_SH7705_CACHE_32KB) && defined(CONFIG_MMU)
+#if defined(CONFIG_MMU) && (defined(CONFIG_CPU_SH4) || \
+       defined(CONFIG_SH7705_CACHE_32KB))
 struct page;
 extern void clear_user_page(void *to, unsigned long address, struct page *pg);
 extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg);
@@ -51,29 +64,20 @@ extern void __copy_user_page(void *to, void *from, void *orig_to);
 #elif defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH3) || !defined(CONFIG_MMU)
 #define clear_user_page(page, vaddr, pg)       clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)    copy_page(to, from)
-#elif defined(CONFIG_CPU_SH4)
-struct page;
-extern void clear_user_page(void *to, unsigned long address, struct page *pg);
-extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg);
-extern void __clear_user_page(void *to, void *orig_to);
-extern void __copy_user_page(void *to, void *from, void *orig_to);
 #endif
 
 /*
  * These are used to make use of C type-checking..
  */
 typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
 
 #define pte_val(x)     ((x).pte)
-#define pmd_val(x)     ((x).pmd)
 #define pgd_val(x)     ((x).pgd)
 #define pgprot_val(x)  ((x).pgprot)
 
 #define __pte(x) ((pte_t) { (x) } )
-#define __pmd(x) ((pmd_t) { (x) } )
 #define __pgd(x) ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
@@ -93,7 +97,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #define __MEMORY_START         CONFIG_MEMORY_START
 #define __MEMORY_SIZE          CONFIG_MEMORY_SIZE
 
-#define PAGE_OFFSET            (0x80000000UL)
+#define PAGE_OFFSET            CONFIG_PAGE_OFFSET
 #define __pa(x)                        ((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)                        ((void *)((unsigned long)(x)+PAGE_OFFSET))
 
@@ -115,5 +119,10 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
+/* vDSO support */
+#ifdef CONFIG_VSYSCALL
+#define __HAVE_ARCH_GATE_AREA
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_PAGE_H */
index 0a523c85b11cf855fd42da11ddc00bf1984ef0da..6ccc948fe216e003aee84018b519c09a8708e848 100644 (file)
@@ -32,6 +32,34 @@ extern struct pci_channel board_pci_channels[];
 #define PCIBIOS_MIN_IO         board_pci_channels->io_resource->start
 #define PCIBIOS_MIN_MEM                board_pci_channels->mem_resource->start
 
+/*
+ * I/O routine helpers
+ */
+#ifdef CONFIG_CPU_SUBTYPE_SH7780
+#define PCI_IO_AREA            0xFE400000
+#define PCI_IO_SIZE            0x00400000
+#else
+#define PCI_IO_AREA            0xFE240000
+#define PCI_IO_SIZE            0X00040000
+#endif
+
+#define PCI_MEM_SIZE           0x01000000
+
+#define SH4_PCIIOBR_MASK       0xFFFC0000
+#define pci_ioaddr(addr)       (PCI_IO_AREA + (addr & ~SH4_PCIIOBR_MASK))
+
+#if defined(CONFIG_PCI)
+#define is_pci_ioaddr(port)            \
+       (((port) >= PCIBIOS_MIN_IO) &&  \
+        ((port) < (PCIBIOS_MIN_IO + PCI_IO_SIZE)))
+#define is_pci_memaddr(port)           \
+       (((port) >= PCIBIOS_MIN_MEM) && \
+        ((port) < (PCIBIOS_MIN_MEM + PCI_MEM_SIZE)))
+#else
+#define is_pci_ioaddr(port)    (0)
+#define is_pci_memaddr(port)   (0)
+#endif
+
 struct pci_dev;
 
 extern void pcibios_set_master(struct pci_dev *dev);
@@ -87,15 +115,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
  */
 #define pci_dac_dma_supported(pci_dev, mask) (0)
 
-/* These macros should be used after a pci_map_sg call has been done
- * to get bus addresses of each of the SG entries and their lengths.
- * You should only work with the number of sg entries pci_map_sg
- * returns, or alternatively stop on the first sg_dma_len(sg) which
- * is 0.
- */
-#define sg_dma_address(sg)     (virt_to_bus((sg)->dma_address))
-#define sg_dma_len(sg)         ((sg)->length)
-
 #ifdef CONFIG_PCI
 static inline void pci_dma_burst_advice(struct pci_dev *pdev,
                                        enum pci_dma_burst_strategy *strat,
@@ -107,11 +126,12 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
 #endif
 
 /* Board-specific fixup routines. */
-extern void pcibios_fixup(void);
-extern void pcibios_fixup_irqs(void);
+void pcibios_fixup(void);
+int pcibios_init_platform(void);
+int pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin);
 
 #ifdef CONFIG_PCI_AUTO
-extern int pciauto_assign_resources(int busno, struct pci_channel *hose);
+int pciauto_assign_resources(int busno, struct pci_channel *hose);
 #endif
 
 static inline void pcibios_add_platform_entries(struct pci_dev *dev)
index f4f233f7a4f575cfec243ee081046f29e2a71ff9..e841465ab4d24214955704852dde0b99a3da35e8 100644 (file)
@@ -1,15 +1,6 @@
 #ifndef __ASM_SH_PGALLOC_H
 #define __ASM_SH_PGALLOC_H
 
-#include <linux/threads.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-
-#define pgd_quicklist ((unsigned long *)0)
-#define pmd_quicklist ((unsigned long *)0)
-#define pte_quicklist ((unsigned long *)0)
-#define pgtable_cache_size 0L
-
 #define pmd_populate_kernel(mm, pmd, pte) \
                set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
 
@@ -24,38 +15,24 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
  */
 static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 {
-       unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t));
-       pgd_t *pgd = (pgd_t *)kmalloc(pgd_size, GFP_KERNEL);
-
-       if (pgd)
-               memset(pgd, 0, pgd_size);
-
-       return pgd;
+       return (pgd_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
 }
 
 static inline void pgd_free(pgd_t *pgd)
 {
-       kfree(pgd);
+       free_page((unsigned long)pgd);
 }
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
                                          unsigned long address)
 {
-       pte_t *pte;
-
-       pte = (pte_t *) __get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
-
-       return pte;
+       return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
 }
 
 static inline struct page *pte_alloc_one(struct mm_struct *mm,
                                         unsigned long address)
 {
-       struct page *pte;
-
-       pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
-
-       return pte;
+       return alloc_page(GFP_KERNEL | __GFP_REPEAT | __GFP_ZERO);
 }
 
 static inline void pte_free_kernel(pte_t *pte)
@@ -75,14 +52,8 @@ static inline void pte_free(struct page *pte)
  * inside the pgd, so has no extra memory associated with it.
  */
 
-#define pmd_alloc_one(mm, addr)                ({ BUG(); ((pmd_t *)2); })
 #define pmd_free(x)                    do { } while (0)
 #define __pmd_free_tlb(tlb,x)          do { } while (0)
-#define pgd_populate(mm, pmd, pte)     BUG()
 #define check_pgt_cache()              do { } while (0)
 
-#ifdef CONFIG_CPU_SH4
-#define PG_mapped                      PG_arch_1
-#endif
-
 #endif /* __ASM_SH_PGALLOC_H */
index 40d41a78041eaa2ed56abf0d668422870ed54e8e..2c8682ad1012531dcaaf54644865fea6b4a52ea0 100644 (file)
@@ -1,42 +1,42 @@
-#ifndef __ASM_SH_PGTABLE_H
-#define __ASM_SH_PGTABLE_H
-
-#include <asm-generic/4level-fixup.h>
-
 /*
+ * This file contains the functions and defines necessary to modify and
+ * use the SuperH page table tree.
+ *
  * Copyright (C) 1999 Niibe Yutaka
- * Copyright (C) 2002, 2003, 2004 Paul Mundt
+ * Copyright (C) 2002 - 2005 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.
  */
+#ifndef __ASM_SH_PGTABLE_H
+#define __ASM_SH_PGTABLE_H
 
-#include <asm/pgtable-2level.h>
+#include <asm-generic/pgtable-nopmd.h>
+#include <asm/page.h>
+
+#define PTRS_PER_PGD           1024
 
-/*
- * This file contains the functions and defines necessary to modify and use
- * the SuperH page table tree.
- */
 #ifndef __ASSEMBLY__
-#include <asm/processor.h>
 #include <asm/addrspace.h>
 #include <asm/fixmap.h>
-#include <linux/threads.h>
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern void paging_init(void);
 
-/*
- * Basically we have the same two-level (which is the logical three level
- * Linux page table layout folded) page tables as the i386.
- */
-
 /*
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
  */
-extern unsigned long empty_zero_page[1024];
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 
 #endif /* !__ASSEMBLY__ */
 
+/* traditional two-level paging structure */
+#define PGDIR_SHIFT    22
+#define PTRS_PER_PMD   1
+#define PTRS_PER_PTE   1024
 #define PMD_SIZE       (1UL << PMD_SHIFT)
 #define PMD_MASK       (~(PMD_SIZE-1))
 #define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
@@ -47,7 +47,6 @@ extern unsigned long empty_zero_page[1024];
 
 #define PTE_PHYS_MASK  0x1ffff000
 
-#ifndef __ASSEMBLY__
 /*
  * First 1MB map is used by fixed purpose.
  * Currently only 4-enty (16kB) is used (see arch/sh/mm/cache.c)
@@ -55,20 +54,41 @@ extern unsigned long empty_zero_page[1024];
 #define VMALLOC_START  (P3SEG+0x00100000)
 #define VMALLOC_END    (FIXADDR_START-2*PAGE_SIZE)
 
-#define        _PAGE_WT        0x001  /* WT-bit on SH-4, 0 on SH-3 */
-#define _PAGE_HW_SHARED        0x002  /* SH-bit  : page is shared among processes */
-#define _PAGE_DIRTY    0x004  /* D-bit   : page changed */
-#define _PAGE_CACHABLE 0x008  /* C-bit   : cachable */
-#define _PAGE_SZ0      0x010  /* SZ0-bit : Size of page */
-#define _PAGE_RW       0x020  /* PR0-bit : write access allowed */
-#define _PAGE_USER     0x040  /* PR1-bit : user space access allowed */
-#define _PAGE_SZ1      0x080  /* SZ1-bit : Size of page (on SH-4) */
-#define _PAGE_PRESENT  0x100  /* V-bit   : page is valid */
-#define _PAGE_PROTNONE 0x200  /* software: if not present  */
-#define _PAGE_ACCESSED         0x400  /* software: page referenced */
-#define _PAGE_U0_SHARED 0x800  /* software: page is shared in user space */
-
-#define        _PAGE_FILE      _PAGE_WT  /* software: pagecache or swap? */
+/*
+ * Linux PTEL encoding.
+ *
+ * Hardware and software bit definitions for the PTEL value:
+ *
+ * - Bits 0 and 7 are reserved on SH-3 (_PAGE_WT and _PAGE_SZ1 on SH-4).
+ *
+ * - Bit 1 is the SH-bit, but is unused on SH-3 due to an MMU bug (the
+ *   hardware PTEL value can't have the SH-bit set when MMUCR.IX is set,
+ *   which is the default in cpu-sh3/mmu_context.h:MMU_CONTROL_INIT).
+ *
+ *   In order to keep this relatively clean, do not use these for defining
+ *   SH-3 specific flags until all of the other unused bits have been
+ *   exhausted.
+ *
+ * - Bit 9 is reserved by everyone and used by _PAGE_PROTNONE.
+ *
+ * - Bits 10 and 11 are low bits of the PPN that are reserved on >= 4K pages.
+ *   Bit 10 is used for _PAGE_ACCESSED, bit 11 remains unused.
+ *
+ * - Bits 31, 30, and 29 remain unused by everyone and can be used for future
+ *   software flags, although care must be taken to update _PAGE_CLEAR_FLAGS.
+ */
+#define        _PAGE_WT        0x001           /* WT-bit on SH-4, 0 on SH-3 */
+#define _PAGE_HW_SHARED        0x002           /* SH-bit  : shared among processes */
+#define _PAGE_DIRTY    0x004           /* D-bit   : page changed */
+#define _PAGE_CACHABLE 0x008           /* C-bit   : cachable */
+#define _PAGE_SZ0      0x010           /* SZ0-bit : Size of page */
+#define _PAGE_RW       0x020           /* PR0-bit : write access allowed */
+#define _PAGE_USER     0x040           /* PR1-bit : user space access allowed */
+#define _PAGE_SZ1      0x080           /* SZ1-bit : Size of page (on SH-4) */
+#define _PAGE_PRESENT  0x100           /* V-bit   : page is valid */
+#define _PAGE_PROTNONE 0x200           /* software: if not present  */
+#define _PAGE_ACCESSED 0x400           /* software: page referenced */
+#define _PAGE_FILE     _PAGE_WT        /* software: pagecache or swap? */
 
 /* software: moves to PTEA.TC (Timing Control) */
 #define _PAGE_PCC_AREA5        0x00000000      /* use BSC registers for area5 */
@@ -83,23 +103,17 @@ extern unsigned long empty_zero_page[1024];
 #define _PAGE_PCC_ATR8 0x60000000      /* Attribute Memory space, 8 bit bus */
 #define _PAGE_PCC_ATR16        0x60000001      /* Attribute Memory space, 6 bit bus */
 
-
-/* Mask which drop software flags
- * We also drop WT bit since it is used for _PAGE_FILE
- * bit in this implementation.
- */
-#define _PAGE_CLEAR_FLAGS      (_PAGE_WT | _PAGE_PROTNONE | _PAGE_ACCESSED | _PAGE_U0_SHARED)
-
-#if defined(CONFIG_CPU_SH3)
-/*
- * MMU on SH-3 has bug on SH-bit: We can't use it if MMUCR.IX=1.
- * Work around: Just drop SH-bit.
- */
-#define _PAGE_FLAGS_HARDWARE_MASK      (0x1fffffff & ~(_PAGE_CLEAR_FLAGS | _PAGE_HW_SHARED))
+/* Mask which drops unused bits from the PTEL value */
+#ifdef CONFIG_CPU_SH3
+#define _PAGE_CLEAR_FLAGS      (_PAGE_PROTNONE | _PAGE_ACCESSED| \
+                                _PAGE_FILE     | _PAGE_SZ1     | \
+                                _PAGE_HW_SHARED)
 #else
-#define _PAGE_FLAGS_HARDWARE_MASK      (0x1fffffff & ~(_PAGE_CLEAR_FLAGS))
+#define _PAGE_CLEAR_FLAGS      (_PAGE_PROTNONE | _PAGE_ACCESSED | _PAGE_FILE)
 #endif
 
+#define _PAGE_FLAGS_HARDWARE_MASK      (0x1fffffff & ~(_PAGE_CLEAR_FLAGS))
+
 /* Hardware flags: SZ0=1 (4k-byte) */
 #define _PAGE_FLAGS_HARD       _PAGE_SZ0
 
@@ -109,15 +123,15 @@ extern unsigned long empty_zero_page[1024];
 #define _PAGE_SZHUGE   (_PAGE_SZ0 | _PAGE_SZ1)
 #endif
 
-#define _PAGE_SHARED   _PAGE_U0_SHARED
-
 #define _PAGE_TABLE    (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
 #define _KERNPG_TABLE  (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
-#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY | _PAGE_SHARED)
+#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY)
+
+#ifndef __ASSEMBLY__
 
 #ifdef CONFIG_MMU
 #define PAGE_NONE      __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_FLAGS_HARD)
-#define PAGE_SHARED    __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_SHARED | _PAGE_FLAGS_HARD)
+#define PAGE_SHARED    __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_CACHABLE |_PAGE_ACCESSED | _PAGE_FLAGS_HARD)
 #define PAGE_COPY      __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_FLAGS_HARD)
 #define PAGE_READONLY  __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_FLAGS_HARD)
 #define PAGE_KERNEL    __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_CACHABLE | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_HW_SHARED | _PAGE_FLAGS_HARD)
@@ -137,12 +151,13 @@ extern unsigned long empty_zero_page[1024];
 #define PAGE_KERNEL_PCC                __pgprot(0)
 #endif
 
+#endif /* __ASSEMBLY__ */
+
 /*
  * As i386 and MIPS, SuperH can't do page protection for execute, and
  * considers that the same as a read.  Also, write permissions imply
- * read permissions. This is the closest we can get..  
+ * read permissions. This is the closest we can get..
  */
-
 #define __P000 PAGE_NONE
 #define __P001 PAGE_READONLY
 #define __P010 PAGE_COPY
@@ -161,6 +176,26 @@ extern unsigned long empty_zero_page[1024];
 #define __S110 PAGE_SHARED
 #define __S111 PAGE_SHARED
 
+#ifndef __ASSEMBLY__
+
+/*
+ * Certain architectures need to do special things when PTEs
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
+/*
+ * (pmds are folded into pgds so this doesn't get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
+
+#define pte_pfn(x)             ((unsigned long)(((x).pte >> PAGE_SHIFT)))
+#define pfn_pte(pfn, prot)     __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define pfn_pmd(pfn, prot)     __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+
 #define pte_none(x)    (!pte_val(x))
 #define pte_present(x) (pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
 #define pte_clear(mm,addr,xp)  do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
@@ -171,7 +206,7 @@ extern unsigned long empty_zero_page[1024];
 #define        pmd_bad(x)      ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
 
 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
-#define pte_page(x)    phys_to_page(pte_val(x)&PTE_PHYS_MASK)
+#define pte_page(x)    phys_to_page(pte_val(x)&PTE_PHYS_MASK)
 
 /*
  * The following only work if pte_present() is true.
@@ -248,6 +283,11 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #define pte_unmap(pte)         do { } while (0)
 #define pte_unmap_nested(pte)  do { } while (0)
 
+#define pte_ERROR(e) \
+       printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pgd_ERROR(e) \
+       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
 struct vm_area_struct;
 extern void update_mmu_cache(struct vm_area_struct * vma,
                             unsigned long address, pte_t pte);
@@ -272,8 +312,6 @@ extern void update_mmu_cache(struct vm_area_struct * vma,
 
 typedef pte_t *pte_addr_t;
 
-#endif /* !__ASSEMBLY__ */
-
 #define kern_addr_valid(addr)  (1)
 
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)                \
@@ -301,5 +339,5 @@ extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t
 
 #include <asm-generic/pgtable.h>
 
+#endif /* !__ASSEMBLY__ */
 #endif /* __ASM_SH_PAGE_H */
-
diff --git a/include/asm-sh/pm.h b/include/asm-sh/pm.h
new file mode 100644 (file)
index 0000000..56fdbd6
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright 2006 (c) Andriy Skulysh <askulysh@gmail.com>
+ *
+ */
+#ifndef __ASM_SH_PM_H
+#define __ASM_SH_PM_H
+
+extern u8 wakeup_start;
+extern u8 wakeup_end;
+
+void pm_enter(void);
+
+#endif
index eeb0f48bb99ead4f5b8d71d92d22df7f7a1d0fbb..474773853cd1a71f3184d85daf62468f3cfc2de0 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/types.h>
 #include <asm/cache.h>
 #include <asm/ptrace.h>
+#include <asm/cpu-features.h>
 
 /*
  * Default implementation of macro that returns current
@@ -38,27 +39,30 @@ enum cpu_type {
        CPU_SH7604,
 
        /* SH-3 types */
-       CPU_SH7705, CPU_SH7707,  CPU_SH7708, CPU_SH7708S, CPU_SH7708R,
-       CPU_SH7709, CPU_SH7709A, CPU_SH7729, CPU_SH7300,
+       CPU_SH7705, CPU_SH7706, CPU_SH7707,
+       CPU_SH7708, CPU_SH7708S, CPU_SH7708R,
+       CPU_SH7709, CPU_SH7709A, CPU_SH7710,
+       CPU_SH7729, CPU_SH7300,
 
        /* SH-4 types */
        CPU_SH7750, CPU_SH7750S, CPU_SH7750R, CPU_SH7751, CPU_SH7751R,
        CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
-       CPU_SH73180, CPU_SH7770, CPU_SH7780, CPU_SH7781,
+       CPU_SH73180, CPU_SH7343, CPU_SH7770, CPU_SH7780, CPU_SH7781,
 
        /* Unknown subtype */
        CPU_SH_NONE
 };
 
 struct sh_cpuinfo {
-       enum cpu_type type;
+       unsigned int type;
        unsigned long loops_per_jiffy;
 
-       struct cache_info icache;
-       struct cache_info dcache;
+       struct cache_info icache;       /* Primary I-cache */
+       struct cache_info dcache;       /* Primary D-cache */
+       struct cache_info scache;       /* Secondary cache */
 
        unsigned long flags;
-};
+} __attribute__ ((aligned(SMP_CACHE_BYTES)));
 
 extern struct sh_cpuinfo boot_cpu_data;
 
@@ -125,17 +129,6 @@ union sh_fpu_union {
        struct sh_fpu_soft_struct soft;
 };
 
-/*
- * Processor flags
- */
-
-#define CPU_HAS_FPU            0x0001  /* Hardware FPU support */
-#define CPU_HAS_P2_FLUSH_BUG   0x0002  /* Need to flush the cache in P2 area */
-#define CPU_HAS_MMU_PAGE_ASSOC 0x0004  /* SH3: TLB way selection bit support */
-#define CPU_HAS_DSP            0x0008  /* SH-DSP: DSP support */
-#define CPU_HAS_PERF_COUNTER   0x0010  /* Hardware performance counters */
-#define CPU_HAS_PTEA           0x0020  /* PTEA register */
-
 struct thread_struct {
        unsigned long sp;
        unsigned long pc;
@@ -149,6 +142,10 @@ struct thread_struct {
        union sh_fpu_union fpu;
 };
 
+typedef struct {
+       unsigned long seg;
+} mm_segment_t;
+
 /* Count of active tasks with UBC settings */
 extern int ubc_usercnt;
 
@@ -266,5 +263,24 @@ extern unsigned long get_wchan(struct task_struct *p);
 #define cpu_sleep()    __asm__ __volatile__ ("sleep" : : : "memory")
 #define cpu_relax()    barrier()
 
+#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \
+    defined(CONFIG_CPU_SH4)
+#define PREFETCH_STRIDE                L1_CACHE_BYTES
+#define ARCH_HAS_PREFETCH
+#define ARCH_HAS_PREFETCHW
+static inline void prefetch(void *x)
+{
+       __asm__ __volatile__ ("pref @%0\n\t" : : "r" (x) : "memory");
+}
+
+#define prefetchw(x)   prefetch(x)
+#endif
+
+#ifdef CONFIG_VSYSCALL
+extern int vsyscall_init(void);
+#else
+#define vsyscall_init() do { } while (0)
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_SH_PROCESSOR_H */
diff --git a/include/asm-sh/r7780rp/ide.h b/include/asm-sh/r7780rp/ide.h
new file mode 100644 (file)
index 0000000..a1ed78e
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __ASM_SH_R7780RP_IDE_H
+#define __ASM_SH_R7780RP_IDE_H
+
+/* Nothing to see here.. */
+#include <asm/mach/r7780rp.h>
+
+#endif /* __ASM_SH_R7780RP_IDE_H */
+
diff --git a/include/asm-sh/r7780rp/r7780rp.h b/include/asm-sh/r7780rp/r7780rp.h
new file mode 100644 (file)
index 0000000..f95d9db
--- /dev/null
@@ -0,0 +1,177 @@
+#ifndef __ASM_SH_RENESAS_R7780RP_H
+#define __ASM_SH_RENESAS_R7780RP_H
+
+/*
+ * linux/include/asm-sh/r7780rp.h
+ *
+ * Copyright (C) 2000  Atom Create Engineering Co., Ltd.
+ *
+ * Renesas Solutions Highlander R7780RP support
+ */
+
+/* Box specific addresses.  */
+#if defined(CONFIG_SH_R7780MP)
+#define PA_BCR          0xa4000000      /* FPGA */
+#define PA_IRLMSK       (PA_BCR+0x0000) /* Interrupt Mask control */
+#define PA_IRLMON       (PA_BCR+0x0002) /* Interrupt Status control */
+#define PA_IRLPRI1      (PA_BCR+0x0004) /* Interrupt Priorty 1 */
+#define PA_IRLPRI2      (PA_BCR+0x0006) /* Interrupt Priorty 2 */
+#define PA_IRLPRI3      (PA_BCR+0x0008) /* Interrupt Priorty 3 */
+#define PA_IRLPRI4      (PA_BCR+0x000a) /* Interrupt Priorty 4 */
+#define PA_RSTCTL       (PA_BCR+0x000c) /* Reset Control */
+#define PA_PCIBD        (PA_BCR+0x000e) /* PCI Board detect control */
+#define PA_PCICD        (PA_BCR+0x0010) /* PCI Conector detect control */
+#define PA_EXTGIO       (PA_BCR+0x0016) /* Extension GPIO Control */
+#define PA_IVDRMON      (PA_BCR+0x0018) /* iVDR Moniter control */
+#define PA_IVDRCTL      (PA_BCR+0x001a) /* iVDR control */
+#define PA_OBLED        (PA_BCR+0x001c) /* On Board LED control */
+#define PA_OBSW         (PA_BCR+0x001e) /* On Board Switch control */
+#define PA_AUDIOSEL     (PA_BCR+0x0020) /* Sound Interface Select control */
+#define PA_EXTPLR       (PA_BCR+0x001e) /* Extention Pin Polarity control */
+#define PA_TPCTL        (PA_BCR+0x0100) /* Touch Panel Access control */
+#define PA_TPDCKCTL     (PA_BCR+0x0102) /* Touch Panel Access data control */
+#define PA_TPCTLCLR     (PA_BCR+0x0104) /* Touch Panel Access control */
+#define PA_TPXPOS       (PA_BCR+0x0106) /* Touch Panel X position control */
+#define PA_TPYPOS       (PA_BCR+0x0108) /* Touch Panel Y position control */
+#define PA_DBSW         (PA_BCR+0x0200) /* Debug Board Switch control */
+#define PA_CFCTL        (PA_BCR+0x0300) /* CF Timing control */
+#define PA_CFPOW        (PA_BCR+0x0302) /* CF Power control */
+#define PA_CFCDINTCLR   (PA_BCR+0x0304) /* CF Insert Interrupt clear */
+#define PA_SCSMR0       (PA_BCR+0x0400) /* SCIF0 Serial mode control */
+#define PA_SCBRR0       (PA_BCR+0x0404) /* SCIF0 Bit rate control */
+#define PA_SCSCR0       (PA_BCR+0x0408) /* SCIF0 Serial control */
+#define PA_SCFTDR0      (PA_BCR+0x040c) /* SCIF0 Send FIFO control */
+#define PA_SCFSR0       (PA_BCR+0x0410) /* SCIF0 Serial status control */
+#define PA_SCFRDR0      (PA_BCR+0x0414) /* SCIF0 Receive FIFO control */
+#define PA_SCFCR0       (PA_BCR+0x0418) /* SCIF0 FIFO control */
+#define PA_SCTFDR0      (PA_BCR+0x041c) /* SCIF0 Send FIFO data control */
+#define PA_SCRFDR0      (PA_BCR+0x0420) /* SCIF0 Receive FIFO data control */
+#define PA_SCSPTR0      (PA_BCR+0x0424) /* SCIF0 Serial Port control */
+#define PA_SCLSR0       (PA_BCR+0x0428) /* SCIF0 Line Status control */
+#define PA_SCRER0       (PA_BCR+0x042c) /* SCIF0 Serial Error control */
+#define PA_SCSMR1       (PA_BCR+0x0500) /* SCIF1 Serial mode control */
+#define PA_SCBRR1       (PA_BCR+0x0504) /* SCIF1 Bit rate control */
+#define PA_SCSCR1       (PA_BCR+0x0508) /* SCIF1 Serial control */
+#define PA_SCFTDR1      (PA_BCR+0x050c) /* SCIF1 Send FIFO control */
+#define PA_SCFSR1       (PA_BCR+0x0510) /* SCIF1 Serial status control */
+#define PA_SCFRDR1      (PA_BCR+0x0514) /* SCIF1 Receive FIFO control */
+#define PA_SCFCR1       (PA_BCR+0x0518) /* SCIF1 FIFO control */
+#define PA_SCTFDR1      (PA_BCR+0x051c) /* SCIF1 Send FIFO data control */
+#define PA_SCRFDR1      (PA_BCR+0x0520) /* SCIF1 Receive FIFO data control */
+#define PA_SCSPTR1      (PA_BCR+0x0524) /* SCIF1 Serial Port control */
+#define PA_SCLSR1       (PA_BCR+0x0528) /* SCIF1 Line Status control */
+#define PA_SCRER1       (PA_BCR+0x052c) /* SCIF1 Serial Error control */
+#define PA_ICCR         (PA_BCR+0x0600) /* Serial control */
+#define PA_SAR          (PA_BCR+0x0602) /* Serial Slave control */
+#define PA_MDR          (PA_BCR+0x0604) /* Serial Mode control */
+#define PA_ADR1         (PA_BCR+0x0606) /* Serial Address1 control */
+#define PA_DAR1         (PA_BCR+0x0646) /* Serial Data1 control */
+#define PA_VERREG       (PA_BCR+0x0700) /* FPGA Version Register */
+#define PA_POFF         (PA_BCR+0x0800) /* System Power Off control */
+#define PA_PMR          (PA_BCR+0x0900) /*  */
+
+#define PA_AX88796L     0xa4100400      /* AX88796L Area */
+#define PA_SC1602BSLB   0xa6000000      /* SC1602BSLB Area */
+#define PA_AREA5_IO     0xb4000000      /* Area 5 IO Memory */
+#define PA_AREA6_IO     0xb8000000      /* Area 6 IO Memory */
+#define PA_IDE_OFFSET   0x1f0           /* CF IDE Offset */
+#define AX88796L_IO_BASE        0x1000  /* AX88796L IO Base Address */
+
+#define IRLCNTR1        (PA_BCR + 0)    /* Interrupt Control Register1 */
+
+#define IRQ_PCISLOT1    65              /* PCI Slot #1 IRQ */
+#define IRQ_PCISLOT2    66              /* PCI Slot #2 IRQ */
+#define IRQ_PCISLOT3    67              /* PCI Slot #3 IRQ */
+#define IRQ_PCISLOT4    68              /* PCI Slot #4 IRQ */
+#define IRQ_CFCARD      1               /* CF Card IRQ */
+// #define IRQ_CFINST   0               /* CF Card Insert IRQ */
+#define IRQ_TP          2               /* Touch Panel IRQ */
+#define IRQ_SCI1        3               /* SCI1 IRQ */
+#define IRQ_SCI0        4               /* SCI0 IRQ */
+#define IRQ_2SERIAL     5               /* Serial IRQ */
+#define IRQ_RTC         6               /* RTC A / B IRQ */
+#define IRQ_EXTENTION6  7               /* EXT6n IRQ */
+#define IRQ_EXTENTION5  8               /* EXT5n IRQ */
+#define IRQ_EXTENTION4  9               /* EXT4n IRQ */
+#define IRQ_EXTENTION2  10              /* EXT2n IRQ */
+#define IRQ_EXTENTION1  11              /* EXT1n IRQ */
+#define IRQ_ONETH       13              /* On board Ethernet IRQ */
+#define IRQ_PSW         14              /* Push Switch IRQ */
+
+#else /* R7780RP */
+
+#define PA_BCR         0xa5000000      /* FPGA */
+#define        PA_IRLMSK       (PA_BCR+0x0000) /* Interrupt Mask control */
+#define PA_IRLMON      (PA_BCR+0x0002) /* Interrupt Status control */
+#define        PA_SDPOW        (PA_BCR+0x0004) /* SD Power control */
+#define        PA_RSTCTL       (PA_BCR+0x0006) /* Device Reset control */
+#define        PA_PCIBD        (PA_BCR+0x0008) /* PCI Board detect control */
+#define        PA_PCICD        (PA_BCR+0x000a) /* PCI Conector detect control */
+#define        PA_ZIGIO1       (PA_BCR+0x000c) /* Zigbee IO control 1 */
+#define        PA_ZIGIO2       (PA_BCR+0x000e) /* Zigbee IO control 2 */
+#define        PA_ZIGIO3       (PA_BCR+0x0010) /* Zigbee IO control 3 */
+#define        PA_ZIGIO4       (PA_BCR+0x0012) /* Zigbee IO control 4 */
+#define        PA_IVDRMON      (PA_BCR+0x0014) /* iVDR Moniter control */
+#define        PA_IVDRCTL      (PA_BCR+0x0016) /* iVDR control */
+#define PA_OBLED       (PA_BCR+0x0018) /* On Board LED control */
+#define PA_OBSW                (PA_BCR+0x001a) /* On Board Switch control */
+#define PA_AUDIOSEL    (PA_BCR+0x001c) /* Sound Interface Select control */
+#define PA_EXTPLR      (PA_BCR+0x001e) /* Extention Pin Polarity control */
+#define PA_TPCTL       (PA_BCR+0x0100) /* Touch Panel Access control */
+#define PA_TPDCKCTL    (PA_BCR+0x0102) /* Touch Panel Access data control */
+#define PA_TPCTLCLR    (PA_BCR+0x0104) /* Touch Panel Access control */
+#define PA_TPXPOS      (PA_BCR+0x0106) /* Touch Panel X position control */
+#define PA_TPYPOS      (PA_BCR+0x0108) /* Touch Panel Y position control */
+#define PA_DBDET       (PA_BCR+0x0200) /* Debug Board detect control */
+#define PA_DBDISPCTL   (PA_BCR+0x0202) /* Debug Board Dot timing control */
+#define PA_DBSW                (PA_BCR+0x0204) /* Debug Board Switch control */
+#define PA_CFCTL       (PA_BCR+0x0300) /* CF Timing control */
+#define PA_CFPOW       (PA_BCR+0x0302) /* CF Power control */
+#define PA_CFCDINTCLR  (PA_BCR+0x0304) /* CF Insert Interrupt clear */
+#define PA_SCSMR       (PA_BCR+0x0400) /* SCIF Serial mode control */
+#define PA_SCBRR       (PA_BCR+0x0402) /* SCIF Bit rate control */
+#define PA_SCSCR       (PA_BCR+0x0404) /* SCIF Serial control */
+#define PA_SCFDTR      (PA_BCR+0x0406) /* SCIF Send FIFO control */
+#define PA_SCFSR       (PA_BCR+0x0408) /* SCIF Serial status control */
+#define PA_SCFRDR      (PA_BCR+0x040a) /* SCIF Receive FIFO control */
+#define PA_SCFCR       (PA_BCR+0x040c) /* SCIF FIFO control */
+#define PA_SCFDR       (PA_BCR+0x040e) /* SCIF FIFO data control */
+#define PA_SCLSR       (PA_BCR+0x0412) /* SCIF Line Status control */
+#define PA_ICCR                (PA_BCR+0x0500) /* Serial control */
+#define PA_SAR         (PA_BCR+0x0502) /* Serial Slave control */
+#define PA_MDR         (PA_BCR+0x0504) /* Serial Mode control */
+#define PA_ADR1                (PA_BCR+0x0506) /* Serial Address1 control */
+#define PA_DAR1                (PA_BCR+0x0546) /* Serial Data1 control */
+#define PA_VERREG      (PA_BCR+0x0600) /* FPGA Version Register */
+
+#define PA_AX88796L    0xa5800400      /* AX88796L Area */
+#define PA_SC1602BSLB  0xa6000000      /* SC1602BSLB Area */
+#define PA_AREA5_IO    0xb4000000      /* Area 5 IO Memory */
+#define PA_AREA6_IO    0xb8000000      /* Area 6 IO Memory */
+#define PA_IDE_OFFSET  0x1f0           /* CF IDE Offset */
+#define AX88796L_IO_BASE       0x1000  /* AX88796L IO Base Address */
+
+#define IRLCNTR1       (PA_BCR + 0)    /* Interrupt Control Register1 */
+
+#define IRQ_PCISLOT1   0               /* PCI Slot #1 IRQ */
+#define IRQ_PCISLOT2   1               /* PCI Slot #2 IRQ */
+#define IRQ_PCISLOT3   2               /* PCI Slot #3 IRQ */
+#define IRQ_PCISLOT4   3               /* PCI Slot #4 IRQ */
+#define IRQ_CFCARD     4               /* CF Card IRQ */
+#define IRQ_CFINST     5               /* CF Card Insert IRQ */
+#define IRQ_M66596     6               /* M66596 IRQ */
+#define IRQ_SDCARD     7               /* SD Card IRQ */
+#define IRQ_TUCHPANEL  8               /* Touch Panel IRQ */
+#define IRQ_SCI                9               /* SCI IRQ */
+#define IRQ_2SERIAL    10              /* Serial IRQ */
+#define        IRQ_EXTENTION   11              /* EXTn IRQ */
+#define IRQ_ONETH      12              /* On board Ethernet IRQ */
+#define IRQ_PSW                13              /* Push Switch IRQ */
+#define IRQ_ZIGBEE     14              /* Ziggbee IO IRQ */
+
+#endif  /* CONFIG_SH_R7780MP */
+
+#define __IO_PREFIX    r7780rp
+#include <asm/io_generic.h>
+
+#endif  /* __ASM_SH_RENESAS_R7780RP */
index cea9cdf9b9252d7037c940594bfac4f0ab60caeb..91aacc96151b2fab63a10aa1eb87f92bf0a80d66 100644 (file)
@@ -1,29 +1,8 @@
 #ifndef _ASM_RTC_H
 #define _ASM_RTC_H
-#ifdef __KERNEL__
 
-#include <asm/machvec.h>
-#include <asm/cpu/rtc.h>
-
-extern void sh_rtc_gettimeofday(struct timespec *ts);
-extern int sh_rtc_settimeofday(const time_t secs);
 extern void (*board_time_init)(void);
-extern void (*rtc_get_time)(struct timespec *);
-extern int (*rtc_set_time)(const time_t);
-
-/* RCR1 Bits */
-#define RCR1_CF                0x80    /* Carry Flag             */
-#define RCR1_CIE       0x10    /* Carry Interrupt Enable */
-#define RCR1_AIE       0x08    /* Alarm Interrupt Enable */
-#define RCR1_AF                0x01    /* Alarm Flag             */
-
-/* RCR2 Bits */
-#define RCR2_PEF       0x80    /* PEriodic interrupt Flag */
-#define RCR2_PESMASK   0x70    /* Periodic interrupt Set  */
-#define RCR2_RTCEN     0x08    /* ENable RTC              */
-#define RCR2_ADJ       0x04    /* ADJustment (30-second)  */
-#define RCR2_RESET     0x02    /* Reset bit               */
-#define RCR2_START     0x01    /* Start bit               */
+extern void (*rtc_sh_get_time)(struct timespec *);
+extern int (*rtc_sh_set_time)(const time_t);
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_RTC_H */
index 4e09ba597e9a06e5746074144081c97df85103c6..b112ae221fd1f4ca0b6ac87cb50909df83037544 100644 (file)
@@ -41,8 +41,6 @@
 
 #define PA_AX88796L    0xaa000400      /* AX88796L Area */
 #define PA_VOYAGER     0xab000000      /* VOYAGER GX Area */
-#define PA_AREA5_IO    0xb4000000      /* Area 5 IO Memory */
-#define PA_AREA6_IO    0xb8000000      /* Area 6 IO Memory */
 #define PA_IDE_OFFSET  0x1f0           /* CF IDE Offset */
 #define AX88796L_IO_BASE       0x1000  /* AX88796L IO Base Address */
 
index 7b91df140022be81858b656f7497f61c637f731a..d19e7cd3b0235759723f3236a03b80ed83a8e29b 100644 (file)
@@ -10,4 +10,13 @@ struct scatterlist {
 
 #define ISA_DMA_THRESHOLD (0x1fffffff)
 
+/* These macros should be used after a pci_map_sg call has been done
+ * to get bus addresses of each of the SG entries and their lengths.
+ * You should only work with the number of sg entries pci_map_sg
+ * returns, or alternatively stop on the first sg_dma_len(sg) which
+ * is 0.
+ */
+#define sg_dma_address(sg)     ((sg)->dma_address)
+#define sg_dma_len(sg)         ((sg)->length)
+
 #endif /* !(__ASM_SH_SCATTERLIST_H) */
diff --git a/include/asm-sh/sci.h b/include/asm-sh/sci.h
new file mode 100644 (file)
index 0000000..52e7366
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __ASM_SH_SCI_H
+#define __ASM_SH_SCI_H
+
+#include <linux/serial_core.h>
+
+/*
+ * Generic header for SuperH SCI(F)
+ *
+ * Do not place SH-specific parts in here, sh64 and h8300 depend on this too.
+ */
+
+/* Offsets into the sci_port->irqs array */
+enum {
+       SCIx_ERI_IRQ,
+       SCIx_RXI_IRQ,
+       SCIx_TXI_IRQ,
+       SCIx_BRI_IRQ,
+       SCIx_NR_IRQS,
+};
+
+/*
+ * Platform device specific platform_data struct
+ */
+struct plat_sci_port {
+       void __iomem    *membase;               /* io cookie */
+       unsigned long   mapbase;                /* resource base */
+       unsigned int    irqs[SCIx_NR_IRQS];     /* ERI, RXI, TXI, BRI */
+       unsigned int    type;                   /* SCI / SCIF / IRDA */
+       upf_t           flags;                  /* UPF_* flags */
+};
+
+int early_sci_setup(struct uart_port *port);
+
+#endif /* __ASM_SH_SCI_H */
similarity index 97%
rename from include/asm-sh/se/se.h
rename to include/asm-sh/se.h
index 791c5da0388a129526e10192b6087f8e8b2cfb27..a1832154a3aacf40400c2982e997bd2cc9e35f61 100644 (file)
@@ -74,4 +74,7 @@
 #define IRQ_STNIC      10
 #endif
 
+#define __IO_PREFIX    se
+#include <asm/io_generic.h>
+
 #endif  /* __ASM_SH_HITACHI_SE_H */
diff --git a/include/asm-sh/se/io.h b/include/asm-sh/se/io.h
deleted file mode 100644 (file)
index 9eeb86c..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * include/asm-sh/io_se.h
- *
- * 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 an Hitachi SolutionEngine
- */
-
-#ifndef _ASM_SH_IO_SE_H
-#define _ASM_SH_IO_SE_H
-
-extern unsigned char se_inb(unsigned long port);
-extern unsigned short se_inw(unsigned long port);
-extern unsigned int se_inl(unsigned long port);
-
-extern void se_outb(unsigned char value, unsigned long port);
-extern void se_outw(unsigned short value, unsigned long port);
-extern void se_outl(unsigned int value, unsigned long port);
-
-extern unsigned char se_inb_p(unsigned long port);
-extern void se_outb_p(unsigned char value, unsigned long port);
-
-extern void se_insb(unsigned long port, void *addr, unsigned long count);
-extern void se_insw(unsigned long port, void *addr, unsigned long count);
-extern void se_insl(unsigned long port, void *addr, unsigned long count);
-extern void se_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void se_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void se_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned long se_isa_port2addr(unsigned long offset);
-
-#endif /* _ASM_SH_IO_SE_H */
similarity index 97%
rename from include/asm-sh/se7300/se7300.h
rename to include/asm-sh/se7300.h
index 3ec1ded86c97477e25399910e573aeddae002635..4e24edccb30d0d964dfc675b57433860620dd766 100644 (file)
@@ -58,4 +58,7 @@
 #define PA_LCD1                0xb8000000
 #define PA_LCD2                0xb8800000
 
+#define __IO_PREFIX    sh7300se
+#include <asm/io_generic.h>
+
 #endif  /* __ASM_SH_HITACHI_SE7300_H */
diff --git a/include/asm-sh/se7300/io.h b/include/asm-sh/se7300/io.h
deleted file mode 100644 (file)
index c6af855..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * include/asm-sh/se7300/io.h
- *
- * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
- * IO functions for SH-Mobile(SH7300) SolutionEngine
- */
-
-#ifndef _ASM_SH_IO_7300SE_H
-#define _ASM_SH_IO_7300SE_H
-
-extern unsigned char sh7300se_inb(unsigned long port);
-extern unsigned short sh7300se_inw(unsigned long port);
-extern unsigned int sh7300se_inl(unsigned long port);
-
-extern void sh7300se_outb(unsigned char value, unsigned long port);
-extern void sh7300se_outw(unsigned short value, unsigned long port);
-extern void sh7300se_outl(unsigned int value, unsigned long port);
-
-extern unsigned char sh7300se_inb_p(unsigned long port);
-extern void sh7300se_outb_p(unsigned char value, unsigned long port);
-
-extern void sh7300se_insb(unsigned long port, void *addr, unsigned long count);
-extern void sh7300se_insw(unsigned long port, void *addr, unsigned long count);
-extern void sh7300se_insl(unsigned long port, void *addr, unsigned long count);
-extern void sh7300se_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void sh7300se_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void sh7300se_outsl(unsigned long port, const void *addr, unsigned long count);
-
-#endif /* _ASM_SH_IO_7300SE_H */
similarity index 97%
rename from include/asm-sh/se73180/se73180.h
rename to include/asm-sh/se73180.h
index f5b93e39e768dddca9c8a02ab9aee783a30f13ca..3a4acb3e38a15239f695d0f95313977f5cb2f2bc 100644 (file)
@@ -59,4 +59,7 @@
 #define PA_LCD1                0xb8000000
 #define PA_LCD2                0xb8800000
 
+#define __IO_PREFIX    sh73180se
+#include <asm/io_generic.h>
+
 #endif  /* __ASM_SH_HITACHI_SE73180_H */
diff --git a/include/asm-sh/se73180/io.h b/include/asm-sh/se73180/io.h
deleted file mode 100644 (file)
index c9cb1b9..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * include/asm-sh/se73180/io.h
- *
- * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
- * Based on include/asm-sh/se7300/io.h
- *
- * IO functions for SH-Mobile3(SH73180) SolutionEngine
- *
- */
-
-#ifndef _ASM_SH_IO_73180SE_H
-#define _ASM_SH_IO_73180SE_H
-
-extern unsigned char sh73180se_inb(unsigned long port);
-extern unsigned short sh73180se_inw(unsigned long port);
-extern unsigned int sh73180se_inl(unsigned long port);
-
-extern void sh73180se_outb(unsigned char value, unsigned long port);
-extern void sh73180se_outw(unsigned short value, unsigned long port);
-extern void sh73180se_outl(unsigned int value, unsigned long port);
-
-extern unsigned char sh73180se_inb_p(unsigned long port);
-extern void sh73180se_outb_p(unsigned char value, unsigned long port);
-
-extern void sh73180se_insb(unsigned long port, void *addr, unsigned long count);
-extern void sh73180se_insw(unsigned long port, void *addr, unsigned long count);
-extern void sh73180se_insl(unsigned long port, void *addr, unsigned long count);
-extern void sh73180se_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void sh73180se_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void sh73180se_outsl(unsigned long port, const void *addr, unsigned long count);
-
-#endif /* _ASM_SH_IO_73180SE_H */
diff --git a/include/asm-sh/se7343.h b/include/asm-sh/se7343.h
new file mode 100644 (file)
index 0000000..e7914a5
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef __ASM_SH_HITACHI_SE7343_H
+#define __ASM_SH_HITACHI_SE7343_H
+
+/*
+ * include/asm-sh/se/se7343.h
+ *
+ * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ *
+ * SH-Mobile SolutionEngine 7343 support
+ */
+
+/* Box specific addresses.  */
+
+/* Area 0 */
+#define PA_ROM         0x00000000      /* EPROM */
+#define PA_ROM_SIZE    0x00400000      /* EPROM size 4M byte(Actually 2MB) */
+#define PA_FROM                0x00400000      /* Flash ROM */
+#define PA_FROM_SIZE   0x00400000      /* Flash size 4M byte */
+#define PA_SRAM                0x00800000      /* SRAM */
+#define PA_FROM_SIZE   0x00400000      /* SRAM size 4M byte */
+/* Area 1 */
+#define PA_EXT1                0x04000000
+#define PA_EXT1_SIZE   0x04000000
+/* Area 2 */
+#define PA_EXT2                0x08000000
+#define PA_EXT2_SIZE   0x04000000
+/* Area 3 */
+#define PA_SDRAM       0x0c000000
+#define PA_SDRAM_SIZE  0x04000000
+/* Area 4 */
+#define PA_PCIC                0x10000000      /* MR-SHPC-01 PCMCIA */
+#define PA_MRSHPC       0xb03fffe0      /* MR-SHPC-01 PCMCIA controller */
+#define PA_MRSHPC_MW1   0xb0400000      /* MR-SHPC-01 memory window base */
+#define PA_MRSHPC_MW2   0xb0500000      /* MR-SHPC-01 attribute window base */
+#define PA_MRSHPC_IO    0xb0600000      /* MR-SHPC-01 I/O window base */
+#define MRSHPC_OPTION   (PA_MRSHPC + 6)
+#define MRSHPC_CSR      (PA_MRSHPC + 8)
+#define MRSHPC_ISR      (PA_MRSHPC + 10)
+#define MRSHPC_ICR      (PA_MRSHPC + 12)
+#define MRSHPC_CPWCR    (PA_MRSHPC + 14)
+#define MRSHPC_MW0CR1   (PA_MRSHPC + 16)
+#define MRSHPC_MW1CR1   (PA_MRSHPC + 18)
+#define MRSHPC_IOWCR1   (PA_MRSHPC + 20)
+#define MRSHPC_MW0CR2   (PA_MRSHPC + 22)
+#define MRSHPC_MW1CR2   (PA_MRSHPC + 24)
+#define MRSHPC_IOWCR2   (PA_MRSHPC + 26)
+#define MRSHPC_CDCR     (PA_MRSHPC + 28)
+#define MRSHPC_PCIC_INFO (PA_MRSHPC + 30)
+#define PA_LED         0xb0C00000      /* LED */
+#define LED_SHIFT       0
+#define PA_DIPSW       0xb0900000      /* Dip switch 31 */
+#define PA_CPLD_MODESET        0xb1400004      /* CPLD Mode set register */
+#define PA_CPLD_ST     0xb1400008      /* CPLD Interrupt status register */
+#define PA_CPLD_IMSK   0xb140000a      /* CPLD Interrupt mask register */
+/* Area 5 */
+#define PA_EXT5                0x14000000
+#define PA_EXT5_SIZE   0x04000000
+/* Area 6 */
+#define PA_LCD1                0xb8000000
+#define PA_LCD2                0xb8800000
+
+#define __IO_PREFIX    sh7343se
+#include <asm/io_generic.h>
+
+/* External Multiplexed interrupts */
+#define PC_IRQ0                OFFCHIP_IRQ_BASE
+#define PC_IRQ1                (PC_IRQ0 + 1)
+#define PC_IRQ2                (PC_IRQ1 + 1)
+#define PC_IRQ3                (PC_IRQ2 + 1)
+
+#define EXT_IRQ0       (PC_IRQ3 + 1)
+#define EXT_IRQ1       (EXT_IRQ0 + 1)
+#define EXT_IRQ2       (EXT_IRQ1 + 1)
+#define EXT_IRQ3       (EXT_IRQ2 + 1)
+
+#define USB_IRQ0       (EXT_IRQ3 + 1)
+#define USB_IRQ1       (USB_IRQ0 + 1)
+
+#define UART_IRQ0      (USB_IRQ1 + 1)
+#define UART_IRQ1      (UART_IRQ0 + 1)
+
+#endif  /* __ASM_SH_HITACHI_SE7343_H */
similarity index 97%
rename from include/asm-sh/se7751/se7751.h
rename to include/asm-sh/se7751.h
index 738e22bebdfbf13bf12da7e70143379c57526105..88cd379d9084013b48df01462c91ee6d706bd6b4 100644 (file)
@@ -65,4 +65,7 @@
 
 #define IRQ_79C973     13
 
+#define __IO_PREFIX    sh7751se
+#include <asm/io_generic.h>
+
 #endif  /* __ASM_SH_HITACHI_7751SE_H */
diff --git a/include/asm-sh/se7751/io.h b/include/asm-sh/se7751/io.h
deleted file mode 100644 (file)
index 78d8f57..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * include/asm-sh/io_7751se.h
- *
- * Modified version of io_se.h for the 7751se-specific functions.
- *
- * May be copied or modified under the terms of the GNU General Public
- * License.  See linux/COPYING for more information.
- *
- * IO functions for an Hitachi SolutionEngine
- */
-
-#ifndef _ASM_SH_IO_7751SE_H
-#define _ASM_SH_IO_7751SE_H
-
-extern unsigned char sh7751se_inb(unsigned long port);
-extern unsigned short sh7751se_inw(unsigned long port);
-extern unsigned int sh7751se_inl(unsigned long port);
-
-extern void sh7751se_outb(unsigned char value, unsigned long port);
-extern void sh7751se_outw(unsigned short value, unsigned long port);
-extern void sh7751se_outl(unsigned int value, unsigned long port);
-
-extern unsigned char sh7751se_inb_p(unsigned long port);
-extern void sh7751se_outb_p(unsigned char value, unsigned long port);
-
-extern void sh7751se_insb(unsigned long port, void *addr, unsigned long count);
-extern void sh7751se_insw(unsigned long port, void *addr, unsigned long count);
-extern void sh7751se_insl(unsigned long port, void *addr, unsigned long count);
-extern void sh7751se_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void sh7751se_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned char sh7751se_readb(unsigned long addr);
-extern unsigned short sh7751se_readw(unsigned long addr);
-extern unsigned int sh7751se_readl(unsigned long addr);
-extern void sh7751se_writeb(unsigned char b, unsigned long addr);
-extern void sh7751se_writew(unsigned short b, unsigned long addr);
-extern void sh7751se_writel(unsigned int b, unsigned long addr);
-
-extern unsigned long sh7751se_isa_port2addr(unsigned long offset);
-
-#endif /* _ASM_SH_IO_7751SE_H */
index d19de7c8df4e258066a8911ddc9064467392c0c5..34ca8a7f06ba86bec5bfc45b2f778c71b3164536 100644 (file)
@@ -4,5 +4,7 @@
 
 #define COMMAND_LINE_SIZE 256
 
+int setup_early_printk(char *);
+
 #endif /* _SH_SETUP_H */
 #endif /* __KERNEL__ */
diff --git a/include/asm-sh/sfp-machine.h b/include/asm-sh/sfp-machine.h
new file mode 100644 (file)
index 0000000..8a6399a
--- /dev/null
@@ -0,0 +1,86 @@
+/* Machine-dependent software floating-point definitions.
+   SuperH kernel version.
+   Copyright (C) 1997,1998,1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Richard Henderson (rth@cygnus.com),
+                 Jakub Jelinek (jj@ultra.linux.cz),
+                 David S. Miller (davem@redhat.com) and
+                 Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, write to the Free Software Foundation, Inc.,
+   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef _SFP_MACHINE_H
+#define _SFP_MACHINE_H
+
+#include <linux/config.h>
+
+#define _FP_W_TYPE_SIZE                32
+#define _FP_W_TYPE             unsigned long
+#define _FP_WS_TYPE            signed long
+#define _FP_I_TYPE             long
+
+#define _FP_MUL_MEAT_S(R,X,Y)                                  \
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y)                                  \
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)                                  \
+  _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)  _FP_DIV_MEAT_1_udiv(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)  _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)  _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S          ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D          ((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q          ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S          0
+#define _FP_NANSIGN_D          0
+#define _FP_NANSIGN_Q          0
+
+#define _FP_KEEPNANFRACP 1
+
+/*
+ * If one NaN is signaling and the other is not,
+ * we choose that one, otherwise we choose X.
+ */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)                      \
+  do {                                                          \
+    if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)          \
+        && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs))     \
+      {                                                         \
+        R##_s = Y##_s;                                          \
+        _FP_FRAC_COPY_##wc(R,Y);                                \
+      }                                                         \
+    else                                                        \
+      {                                                         \
+        R##_s = X##_s;                                          \
+        _FP_FRAC_COPY_##wc(R,X);                                \
+      }                                                         \
+    R##_c = FP_CLS_NAN;                                         \
+  } while (0)
+
+//#define FP_ROUNDMODE         FPSCR_RM
+#define FP_DENORM_ZERO         1/*FPSCR_DN*/
+
+/* Exception flags. */
+#define FP_EX_INVALID          (1<<4)
+#define FP_EX_DIVZERO          (1<<3)
+#define FP_EX_OVERFLOW         (1<<2)
+#define FP_EX_UNDERFLOW                (1<<1)
+#define FP_EX_INEXACT          (1<<0)
+
+#endif
+
index 25792e9831ea4ab86e65b5cae37e5138e74b6b79..df3b187ef8836e7168264e5546ae0017b494964b 100644 (file)
 #define IRL3_IPR_POS   0
 #define IRL3_PRIORITY  4
 
-
-extern unsigned long sh03_isa_port2addr(unsigned long offset);
-
-extern void setup_sh03(void);
-extern void init_sh03_IRQ(void);
-extern void heartbeat_sh03(void);
-
-extern void sh03_rtc_gettimeofday(struct timeval *tv);
-extern int sh03_rtc_settimeofday(const struct timeval *tv);
+void heartbeat_sh03(void);
 
 #endif /* _ASM_SH_IO_SH03_H */
diff --git a/include/asm-sh/sh2000/sh2000.h b/include/asm-sh/sh2000/sh2000.h
deleted file mode 100644 (file)
index 8d54732..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ASM_SH_SH2000_SH2000_H
-#define __ASM_SH_SH2000_SH2000_H
-
-/* arch/sh/boards/sh2000/setup.c */
-extern int setup_sh2000(void);
-
-#endif /* __ASM_SH_SH2000_SH2000_H */
-
diff --git a/include/asm-sh/shmin/shmin.h b/include/asm-sh/shmin/shmin.h
new file mode 100644 (file)
index 0000000..36ba138
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __ASM_SH_SHMIN_H
+#define __ASM_SH_SHMIN_H
+
+#define SHMIN_IO_BASE 0xb0000000UL
+
+#define SHMIN_NE_IRQ IRQ2_IRQ
+#define SHMIN_NE_BASE 0x300
+
+#endif
index 0a95604b9b66d9fdfe8704e943b366be471d0303..ba1758d90106267f23ea1c05362e59f1805ff40d 100644 (file)
@@ -1,8 +1,22 @@
+/*
+ * include/asm-sh/shmparam.h
+ *
+ * Copyright (C) 1999 Niibe Yutaka
+ * 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.
+ */
 #ifndef __ASM_SH_SHMPARAM_H
 #define __ASM_SH_SHMPARAM_H
-#ifdef __KERNEL__
 
-#include <asm/cpu/shmparam.h>
+/*
+ * SH-4 and SH-3 7705 have an aliasing dcache. Bump this up to a sensible value
+ * for everyone, and work out the specifics from the probed cache descriptor.
+ */
+#define        SHMLBA  0x4000           /* attach addr a multiple of this */
+
+#define __ARCH_FORCE_SHMLBA
 
-#endif /* __KERNEL__ */
 #endif /* __ASM_SH_SHMPARAM_H */
index f57c4fe9692a97d27557bdeaabc9f33b0791badc..71ecddf70db382f7153b6f6888eec216056914b9 100644 (file)
 #include <asm/atomic.h>
 #include <asm/current.h>
 
-extern cpumask_t cpu_online_map;
-extern cpumask_t cpu_possible_map;
-
-#define cpu_online(cpu)                cpu_isset(cpu, cpu_online_map)
-
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
 /* I've no idea what the real meaning of this is */
similarity index 62%
rename from include/asm-sh/snapgear/io.h
rename to include/asm-sh/snapgear.h
index bfa97ac0628019448c5c76cd0febe93f167c5cbf..6b5e4ddc073accbdb7133b7831b53303fdccc086 100644 (file)
 #define IRL3_PRIORITY  4
 #endif
 
-extern unsigned char snapgear_inb(unsigned long port);
-extern unsigned short snapgear_inw(unsigned long port);
-extern unsigned int snapgear_inl(unsigned long port);
-
-extern void snapgear_outb(unsigned char value, unsigned long port);
-extern void snapgear_outw(unsigned short value, unsigned long port);
-extern void snapgear_outl(unsigned int value, unsigned long port);
-
-extern unsigned char snapgear_inb_p(unsigned long port);
-extern void snapgear_outb_p(unsigned char value, unsigned long port);
-
-extern void snapgear_insl(unsigned long port, void *addr, unsigned long count);
-extern void snapgear_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned long snapgear_isa_port2addr(unsigned long offset);
+#define __IO_PREFIX    snapgear
+#include <asm/io_generic.h>
 
 #ifdef CONFIG_SH_SECUREEDGE5410
 /*
@@ -79,14 +66,14 @@ extern unsigned long snapgear_isa_port2addr(unsigned long offset);
  * D12        -                      RTS RESET
  */
 
- #define SECUREEDGE_IOPORT_ADDR ((volatile short *) 0xb0000000)
- extern unsigned short secureedge5410_ioport;
+#define SECUREEDGE_IOPORT_ADDR ((volatile short *) 0xb0000000)
+extern unsigned short secureedge5410_ioport;
 
- #define SECUREEDGE_WRITE_IOPORT(val, mask) (*SECUREEDGE_IOPORT_ADDR = \
-                (secureedge5410_ioport = \
-                               ((secureedge5410_ioport & ~(mask)) | ((val) & (mask)))))
- #define SECUREEDGE_READ_IOPORT() \
-                ((*SECUREEDGE_IOPORT_ADDR&0x0817) | (secureedge5410_ioport&~0x0817))
+#define SECUREEDGE_WRITE_IOPORT(val, mask) (*SECUREEDGE_IOPORT_ADDR = \
+        (secureedge5410_ioport = \
+                       ((secureedge5410_ioport & ~(mask)) | ((val) & (mask)))))
+#define SECUREEDGE_READ_IOPORT() \
+        ((*SECUREEDGE_IOPORT_ADDR&0x0817) | (secureedge5410_ioport&~0x0817))
 #endif
 
 #endif /* _ASM_SH_IO_SNAPGEAR_H */
index ad35ad4958f44df04d7abda10e132c92d707e8bd..6c1f8fde5ac4a8e6a73c6d5059491db8c7e56554 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2002 Paul Mundt
  */
 
+#include <asm/types.h>
 
 /*
  *     switch_to() should switch tasks to task nr n, first
@@ -66,13 +67,20 @@ static inline void sched_cacheflush(void)
 {
 }
 
-#define nop() __asm__ __volatile__ ("nop")
-
-
-#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+#ifdef CONFIG_CPU_SH4A
+#define __icbi()                       \
+{                                      \
+       unsigned long __addr;           \
+       __addr = 0xa8000000;            \
+       __asm__ __volatile__(           \
+               "icbi   %0\n\t"         \
+               : /* no output */       \
+               : "m" (__m(__addr)));   \
+}
+#endif
 
-static __inline__ unsigned long tas(volatile int *m)
-{ /* #define tas(ptr) (xchg((ptr),1)) */
+static inline unsigned long tas(volatile int *m)
+{
        unsigned long retval;
 
        __asm__ __volatile__ ("tas.b    @%1\n\t"
@@ -81,12 +89,33 @@ static __inline__ unsigned long tas(volatile int *m)
        return retval;
 }
 
-extern void __xchg_called_with_bad_pointer(void);
-
-#define mb()   __asm__ __volatile__ ("": : :"memory")
-#define rmb()  mb()
-#define wmb()  __asm__ __volatile__ ("": : :"memory")
+/*
+ * A brief note on ctrl_barrier(), the control register write barrier.
+ *
+ * Legacy SH cores typically require a sequence of 8 nops after
+ * modification of a control register in order for the changes to take
+ * effect. On newer cores (like the sh4a and sh5) this is accomplished
+ * with icbi.
+ *
+ * Also note that on sh4a in the icbi case we can forego a synco for the
+ * write barrier, as it's not necessary for control registers.
+ *
+ * Historically we have only done this type of barrier for the MMUCR, but
+ * it's also necessary for the CCR, so we make it generic here instead.
+ */
+#ifdef CONFIG_CPU_SH4A
+#define mb()           __asm__ __volatile__ ("synco": : :"memory")
+#define rmb()          mb()
+#define wmb()          __asm__ __volatile__ ("synco": : :"memory")
+#define ctrl_barrier() __icbi()
+#define read_barrier_depends() do { } while(0)
+#else
+#define mb()           __asm__ __volatile__ ("": : :"memory")
+#define rmb()          mb()
+#define wmb()          __asm__ __volatile__ ("": : :"memory")
+#define ctrl_barrier() __asm__ __volatile__ ("nop;nop;nop;nop;nop;nop;nop;nop")
 #define read_barrier_depends() do { } while(0)
+#endif
 
 #ifdef CONFIG_SMP
 #define smp_mb()       mb()
@@ -103,7 +132,8 @@ extern void __xchg_called_with_bad_pointer(void);
 #define set_mb(var, value) do { xchg(&var, value); } while (0)
 
 /* Interrupt Control */
-static __inline__ void local_irq_enable(void)
+#ifdef CONFIG_CPU_HAS_SR_RB
+static inline void local_irq_enable(void)
 {
        unsigned long __dummy0, __dummy1;
 
@@ -116,8 +146,22 @@ static __inline__ void local_irq_enable(void)
                             : "1" (~0x000000f0)
                             : "memory");
 }
+#else
+static inline void local_irq_enable(void)
+{
+       unsigned long __dummy0, __dummy1;
+
+       __asm__ __volatile__ (
+               "stc    sr, %0\n\t"
+               "and    %1, %0\n\t"
+               "ldc    %0, sr\n\t"
+               : "=&r" (__dummy0), "=r" (__dummy1)
+               : "1" (~0x000000f0)
+               : "memory");
+}
+#endif
 
-static __inline__ void local_irq_disable(void)
+static inline void local_irq_disable(void)
 {
        unsigned long __dummy;
        __asm__ __volatile__("stc       sr, %0\n\t"
@@ -128,6 +172,31 @@ static __inline__ void local_irq_disable(void)
                             : "memory");
 }
 
+static inline void set_bl_bit(void)
+{
+       unsigned long __dummy0, __dummy1;
+
+       __asm__ __volatile__ ("stc      sr, %0\n\t"
+                            "or        %2, %0\n\t"
+                            "and       %3, %0\n\t"
+                            "ldc       %0, sr"
+                            : "=&r" (__dummy0), "=r" (__dummy1)
+                            : "r" (0x10000000), "r" (0xffffff0f)
+                            : "memory");
+}
+
+static inline void clear_bl_bit(void)
+{
+       unsigned long __dummy0, __dummy1;
+
+       __asm__ __volatile__ ("stc      sr, %0\n\t"
+                            "and       %2, %0\n\t"
+                            "ldc       %0, sr"
+                            : "=&r" (__dummy0), "=r" (__dummy1)
+                            : "1" (~0x10000000)
+                            : "memory");
+}
+
 #define local_save_flags(x) \
        __asm__("stc sr, %0; and #0xf0, %0" : "=&z" (x) :/**/: "memory" )
 
@@ -138,7 +207,7 @@ static __inline__ void local_irq_disable(void)
        (flags != 0);                   \
 })
 
-static __inline__ unsigned long local_irq_save(void)
+static inline unsigned long local_irq_save(void)
 {
        unsigned long flags, __dummy;
 
@@ -154,35 +223,9 @@ static __inline__ unsigned long local_irq_save(void)
        return flags;
 }
 
-#ifdef DEBUG_CLI_STI
-static __inline__ void  local_irq_restore(unsigned long x)
-{
-       if ((x & 0x000000f0) != 0x000000f0)
-               local_irq_enable();
-       else {
-               unsigned long flags;
-               local_save_flags(flags);
-
-               if (flags == 0) {
-                       extern void dump_stack(void);
-                       printk(KERN_ERR "BUG!\n");
-                       dump_stack();
-                       local_irq_disable();
-               }
-       }
-}
-#else
-#define local_irq_restore(x) do {                      \
-       if ((x & 0x000000f0) != 0x000000f0)             \
-               local_irq_enable();                             \
-} while (0)
-#endif
-
-#define really_restore_flags(x) do {                   \
+#define local_irq_restore(x) do {                      \
        if ((x & 0x000000f0) != 0x000000f0)             \
-               local_irq_enable();                             \
-       else                                            \
-               local_irq_disable();                            \
+               local_irq_enable();                     \
 } while (0)
 
 /*
@@ -210,8 +253,8 @@ do {                                        \
 #define back_to_P1()                                   \
 do {                                                   \
        unsigned long __dummy;                          \
+       ctrl_barrier();                                 \
        __asm__ __volatile__(                           \
-               "nop;nop;nop;nop;nop;nop;nop\n\t"       \
                "mov.l  1f, %0\n\t"                     \
                "jmp    @%0\n\t"                        \
                " nop\n\t"                              \
@@ -224,7 +267,7 @@ do {                                                        \
 /* For spinlocks etc */
 #define local_irq_save(x)      x = local_irq_save()
 
-static __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
+static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
 {
        unsigned long flags, retval;
 
@@ -235,7 +278,7 @@ static __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
        return retval;
 }
 
-static __inline__ unsigned long xchg_u8(volatile unsigned char * m, unsigned long val)
+static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val)
 {
        unsigned long flags, retval;
 
@@ -246,20 +289,70 @@ static __inline__ unsigned long xchg_u8(volatile unsigned char * m, unsigned lon
        return retval;
 }
 
-static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+extern void __xchg_called_with_bad_pointer(void);
+
+#define __xchg(ptr, x, size)                           \
+({                                                     \
+       unsigned long __xchg__res;                      \
+       volatile void *__xchg_ptr = (ptr);              \
+       switch (size) {                                 \
+       case 4:                                         \
+               __xchg__res = xchg_u32(__xchg_ptr, x);  \
+               break;                                  \
+       case 1:                                         \
+               __xchg__res = xchg_u8(__xchg_ptr, x);   \
+               break;                                  \
+       default:                                        \
+               __xchg_called_with_bad_pointer();       \
+               __xchg__res = x;                        \
+               break;                                  \
+       }                                               \
+                                                       \
+       __xchg__res;                                    \
+})
+
+#define xchg(ptr,x)    \
+       ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr))))
+
+static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old,
+       unsigned long new)
+{
+       __u32 retval;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       retval = *m;
+       if (retval == old)
+               *m = new;
+       local_irq_restore(flags);       /* implies memory barrier  */
+       return retval;
+}
+
+/* This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg(). */
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+#define __HAVE_ARCH_CMPXCHG 1
+
+static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
+               unsigned long new, int size)
 {
        switch (size) {
        case 4:
-               return xchg_u32(ptr, x);
-               break;
-       case 1:
-               return xchg_u8(ptr, x);
-               break;
+               return __cmpxchg_u32(ptr, old, new);
        }
-       __xchg_called_with_bad_pointer();
-       return x;
+       __cmpxchg_called_with_bad_pointer();
+       return old;
 }
 
+#define cmpxchg(ptr,o,n)                                                \
+  ({                                                                    \
+     __typeof__(*(ptr)) _o_ = (o);                                      \
+     __typeof__(*(ptr)) _n_ = (n);                                      \
+     (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,          \
+                                   (unsigned long)_n_, sizeof(*(ptr))); \
+  })
+
 /* XXX
  * disable hlt during certain critical i/o operations
  */
diff --git a/include/asm-sh/systemh/io.h b/include/asm-sh/systemh/io.h
deleted file mode 100644 (file)
index 327849b..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * include/asm-sh/systemh/io.h
- *
- * Stupid I/O definitions for SystemH, cloned from SE7751.
- *
- * Copyright (C) 2003  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.
- */
-#ifndef __ASM_SH_SYSTEMH_IO_H
-#define __ASM_SH_SYSTEMH_IO_H
-
-extern unsigned char sh7751systemh_inb(unsigned long port);
-extern unsigned short sh7751systemh_inw(unsigned long port);
-extern unsigned int sh7751systemh_inl(unsigned long port);
-
-extern void sh7751systemh_outb(unsigned char value, unsigned long port);
-extern void sh7751systemh_outw(unsigned short value, unsigned long port);
-extern void sh7751systemh_outl(unsigned int value, unsigned long port);
-
-extern unsigned char sh7751systemh_inb_p(unsigned long port);
-extern void sh7751systemh_outb_p(unsigned char value, unsigned long port);
-
-extern void sh7751systemh_insb(unsigned long port, void *addr, unsigned long count);
-extern void sh7751systemh_insw(unsigned long port, void *addr, unsigned long count);
-extern void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count);
-extern void sh7751systemh_outsb(unsigned long port, const void *addr, unsigned long count);
-extern void sh7751systemh_outsw(unsigned long port, const void *addr, unsigned long count);
-extern void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count);
-
-extern unsigned char sh7751systemh_readb(unsigned long addr);
-extern unsigned short sh7751systemh_readw(unsigned long addr);
-extern unsigned int sh7751systemh_readl(unsigned long addr);
-extern void sh7751systemh_writeb(unsigned char b, unsigned long addr);
-extern void sh7751systemh_writew(unsigned short b, unsigned long addr);
-extern void sh7751systemh_writel(unsigned int b, unsigned long addr);
-
-extern unsigned long sh7751systemh_isa_port2addr(unsigned long offset);
-
-#endif /* __ASM_SH_SYSTEMH_IO_H */
-
similarity index 97%
rename from include/asm-sh/systemh/7751systemh.h
rename to include/asm-sh/systemh7751.h
index 4170531bdbd937206bf4ee4b84129cae2922d4f7..b143bb2a2ca757a8128f14185fc2b6eabf6f931d 100644 (file)
@@ -65,4 +65,7 @@
 
 #define IRQ_79C973     13
 
+#define __IO_PREFIX    sh7751systemh
+#include <asm/io_generic.h>
+
 #endif  /* __ASM_SH_SYSTEMH_7751SYSTEMH_H */
index 7345350d98c0c2fe16a3b6029c0f071e1a2fd157..3ebc3f9039ebe3f6cebdaa43c913c5c93dbd0547 100644 (file)
@@ -9,8 +9,8 @@
  *  Copyright (C) 2002  David Howells (dhowells@redhat.com)
  *  - Incorporating suggestions made by Linus Torvalds and Dave Miller
  */
-
 #ifdef __KERNEL__
+#include <asm/page.h>
 
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
@@ -21,7 +21,10 @@ struct thread_info {
        unsigned long           flags;          /* low level flags */
        __u32                   cpu;
        int                     preempt_count; /* 0 => preemptable, <0 => BUG */
+       mm_segment_t            addr_limit;     /* thread address space */
        struct restart_block    restart_block;
+       unsigned long           previous_sp;    /* sp of previous stack in case
+                                                  of nested IRQ stacks */
        __u8                    supervisor_stack[0];
 };
 
@@ -29,6 +32,13 @@ struct thread_info {
 
 #define PREEMPT_ACTIVE         0x10000000
 
+#ifdef CONFIG_4KSTACKS
+#define THREAD_SIZE            (PAGE_SIZE)
+#else
+#define THREAD_SIZE            (PAGE_SIZE * 2)
+#endif
+#define STACK_WARN             (THREAD_SIZE / 8)
+
 /*
  * macros/functions for gaining access to the thread information structure
  */
@@ -40,6 +50,7 @@ struct thread_info {
        .flags          = 0,                    \
        .cpu            = 0,                    \
        .preempt_count  = 1,                    \
+       .addr_limit     = KERNEL_DS,            \
        .restart_block  = {                     \
                .fn = do_no_restart_syscall,    \
        },                                      \
@@ -48,24 +59,42 @@ struct thread_info {
 #define init_thread_info       (init_thread_union.thread_info)
 #define init_stack             (init_thread_union.stack)
 
+/* how to get the current stack pointer from C */
+register unsigned long current_stack_pointer asm("r15") __attribute_used__;
+
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
        struct thread_info *ti;
+#ifdef CONFIG_CPU_HAS_SR_RB
        __asm__("stc    r7_bank, %0" : "=r" (ti));
+#else
+       unsigned long __dummy;
+
+       __asm__ __volatile__ (
+               "mov    r15, %0\n\t"
+               "and    %1, %0\n\t"
+               : "=&r" (ti), "=r" (__dummy)
+               : "1" (~(THREAD_SIZE - 1))
+               : "memory");
+#endif
+
        return ti;
 }
 
 /* thread information allocation */
-#define THREAD_SIZE (2*PAGE_SIZE)
-#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#define alloc_thread_info(ti)  kzalloc(THREAD_SIZE, GFP_KERNEL)
+#else
+#define alloc_thread_info(ti)  kmalloc(THREAD_SIZE, GFP_KERNEL)
+#endif
+#define free_thread_info(ti)   kfree(ti)
 
 #else /* !__ASSEMBLY__ */
 
 /* how to get the thread information struct from ASM */
 #define GET_THREAD_INFO(reg) \
-       stc     r7_bank, reg
+       stc     r7_bank, reg
 
 #endif
 
@@ -79,18 +108,18 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_NOTIFY_RESUME      1       /* resumption notification requested */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
+#define TIF_RESTORE_SIGMASK    4       /* restore signal mask in do_signal() */
 #define TIF_USEDFPU            16      /* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG     17      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             18
-#define TIF_USERSPACE          31      /* true if FS sets userspace */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
+#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
-#define _TIF_USERSPACE         (1<<TIF_USERSPACE)
 
 #define _TIF_WORK_MASK         0x000000FE      /* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK      0x000000FF      /* work to do on any return to u-space */
index dd6579c0b04cf01cca86ad41238394d74697e244..c7ab28095ba0ea4ffabe410108d57a33c9f5e56b 100644 (file)
@@ -6,6 +6,8 @@
 
 struct sys_timer_ops {
        int (*init)(void);
+       int (*start)(void);
+       int (*stop)(void);
        unsigned long (*get_offset)(void);
        unsigned long (*get_frequency)(void);
 };
diff --git a/include/asm-sh/titan.h b/include/asm-sh/titan.h
new file mode 100644 (file)
index 0000000..270a4f4
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Platform defintions for Titan
+ */
+
+#ifndef _ASM_SH_TITAN_TITAN_H
+#define _ASM_SH_TITAN_TITAN_H
+
+#define __IO_PREFIX titan
+#include <asm/io_generic.h>
+
+/* IRQ assignments */
+#define TITAN_IRQ_WAN          2       /* eth0 (WAN) */
+#define TITAN_IRQ_LAN          5       /* eth1 (LAN) */
+#define TITAN_IRQ_MPCIA                8       /* mPCI A */
+#define TITAN_IRQ_MPCIB                11      /* mPCI B */
+#define TITAN_IRQ_USB          11      /* USB */
+
+/*
+ * The external interrupt lines, these take up ints 0 - 15 inclusive
+ * depending on the priority for the interrupt.  In fact the priority
+ * is the interrupt :-)
+ */
+#define IRL0_IRQ       0
+#define IRL0_IPR_ADDR  INTC_IPRD
+#define IRL0_IPR_POS   3
+#define IRL0_PRIORITY  8
+
+#define IRL1_IRQ       1
+#define IRL1_IPR_ADDR  INTC_IPRD
+#define IRL1_IPR_POS   2
+#define IRL1_PRIORITY  8
+
+#define IRL2_IRQ       2
+#define IRL2_IPR_ADDR  INTC_IPRD
+#define IRL2_IPR_POS   1
+#define IRL2_PRIORITY  8
+
+#define IRL3_IRQ       3
+#define IRL3_IPR_ADDR  INTC_IPRD
+#define IRL3_IPR_POS   0
+#define IRL3_PRIORITY  8
+
+#endif
index 2cb01861e7c550babe2e44409aa0be3942d2415a..5c49ed6715f2a620a6d75d02583d76c16e1a6ee7 100644 (file)
 #include <linux/errno.h>
 #include <linux/sched.h>
 
-/*
- * NOTE: Macro/functions in this file depends on threads_info.h implementation.
- * Assumes:
- * TI_FLAGS == 8
- * TIF_USERSPACE == 31
- * USER_ADDR_LIMIT == 0x80000000
- */
-
 #define VERIFY_READ    0
 #define VERIFY_WRITE   1
 
-typedef struct {
-       unsigned int is_user_space;
-} mm_segment_t;
-
 /*
  * The fs value determines whether argument validity checking should be
  * performed or not.  If get_fs() == USER_DS, checking is performed, with
@@ -40,16 +28,18 @@ typedef struct {
  */
 
 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
-#define segment_eq(a,b)        ((a).is_user_space == (b).is_user_space)
 
-#define USER_ADDR_LIMIT        0x80000000
+#define KERNEL_DS      MAKE_MM_SEG(0xFFFFFFFFUL)
+#define USER_DS                MAKE_MM_SEG(PAGE_OFFSET)
 
-#define KERNEL_DS      MAKE_MM_SEG(0)
-#define USER_DS                MAKE_MM_SEG(1)
+#define segment_eq(a,b)        ((a).seg == (b).seg)
 
 #define get_ds()       (KERNEL_DS)
 
 #if !defined(CONFIG_MMU)
+/* NOMMU is always true */
+#define __addr_ok(addr) (1)
+
 static inline mm_segment_t get_fs(void)
 {
        return USER_DS;
@@ -76,31 +66,11 @@ static inline int __access_ok(unsigned long addr, unsigned long size)
        return ((addr >= memory_start) && ((addr + size) < memory_end));
 }
 #else /* CONFIG_MMU */
-static inline mm_segment_t get_fs(void)
-{
-       return MAKE_MM_SEG(test_thread_flag(TIF_USERSPACE));
-}
+#define __addr_ok(addr) \
+       ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg))
 
-static inline void set_fs(mm_segment_t s)
-{
-       unsigned long ti, flag;
-       __asm__ __volatile__(
-               "stc    r7_bank, %0\n\t"
-               "mov.l  @(8,%0), %1\n\t"
-               "shal   %1\n\t"
-               "cmp/pl %2\n\t"
-               "rotcr  %1\n\t"
-               "mov.l  %1, @(8,%0)"
-               : "=&r" (ti), "=&r" (flag)
-               : "r" (s.is_user_space)
-               : "t");
-/****
-       if (s.is_user_space)
-               set_thread_flag(TIF_USERSPACE);
-       else
-               clear_thread_flag(TIF_USERSPACE);
-****/
-}
+#define get_fs()       (current_thread_info()->addr_limit)
+#define set_fs(x)      (current_thread_info()->addr_limit = (x))
 
 /*
  * __access_ok: Check if address with size is OK or not.
@@ -108,7 +78,7 @@ static inline void set_fs(mm_segment_t s)
  * We do three checks:
  * (1) is it user space? 
  * (2) addr + size --> carry?
- * (3) addr + size >= 0x80000000  (USER_ADDR_LIMIT)
+ * (3) addr + size >= 0x80000000  (PAGE_OFFSET)
  *
  * (1) (2) (3) | RESULT
  *  0   0   0  |  ok
@@ -201,6 +171,7 @@ do {                                                                \
        __gu_err;                                               \
 })
 
+#ifdef CONFIG_MMU
 #define __get_user_check(x,ptr,size)                           \
 ({                                                             \
        long __gu_err, __gu_val;                                \
@@ -290,6 +261,18 @@ __asm__("stc       r7_bank, %1\n\t"                \
        : "r" (addr)                            \
        : "t");                                 \
 })
+#else /* CONFIG_MMU */
+#define __get_user_check(x,ptr,size)                                   \
+({                                                                     \
+       long __gu_err, __gu_val;                                        \
+       if (__access_ok((unsigned long)(ptr), (size))) {                \
+               __get_user_size(__gu_val, (ptr), (size), __gu_err);     \
+               (x) = (__typeof__(*(ptr)))__gu_val;                     \
+       } else                                                          \
+               __gu_err = -EFAULT;                                     \
+       __gu_err;                                                       \
+})
+#endif
 
 #define __get_user_asm(x, addr, err, insn) \
 ({ \
@@ -541,7 +524,7 @@ static __inline__ long __strnlen_user(const char __user *__s, long __n)
                "3:\n\t"
                "mov.l  4f, %1\n\t"
                "jmp    @%1\n\t"
-               " mov   %5, %0\n"
+               " mov   #0, %0\n"
                ".balign 4\n"
                "4:     .long 2b\n"
                ".previous\n"
@@ -550,26 +533,20 @@ static __inline__ long __strnlen_user(const char __user *__s, long __n)
                "       .long 1b,3b\n"
                ".previous"
                : "=z" (res), "=&r" (__dummy)
-               : "0" (0), "r" (__s), "r" (__n), "i" (-EFAULT)
+               : "0" (0), "r" (__s), "r" (__n)
                : "t");
        return res;
 }
 
 static __inline__ long strnlen_user(const char __user *s, long n)
 {
-       if (!access_ok(VERIFY_READ, s, n))
+       if (!__addr_ok(s))
                return 0;
        else
                return __strnlen_user(s, n);
 }
 
-static __inline__ long strlen_user(const char __user *s)
-{
-       if (!access_ok(VERIFY_READ, s, 0))
-               return 0;
-       else
-               return __strnlen_user(s, ~0UL >> 1);
-}
+#define strlen_user(str)       strnlen_user(str, ~0UL >> 1)
 
 /*
  * The exception table consists of pairs of addresses: the first is the
index 76b5430cb4580ae09995ce8979a078ceb4ba84e9..5d5e9f94def587192e726bb59c5079585580629f 100644 (file)
 #define __NR_mq_getsetattr      (__NR_mq_open+5)
 #define __NR_kexec_load                283
 #define __NR_waitid            284
-#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
+/* #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_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_unlinkat          301
+#define __NR_renameat          302
+#define __NR_linkat            303
+#define __NR_symlinkat         304
+#define __NR_readlinkat                305
+#define __NR_fchmodat          306
+#define __NR_faccessat         307
+#define __NR_pselect6          308
+#define __NR_ppoll             309
+#define __NR_unshare           310
+#define __NR_set_robust_list   311
+#define __NR_get_robust_list   312
+#define __NR_splice            313
+#define __NR_sync_file_range   314
+#define __NR_tee               315
+#define __NR_vmsplice          316
 
-
-#define NR_syscalls 293
+#define NR_syscalls 317
 
 #ifdef __KERNEL__
 
-/* user-visible error numbers are in the range -1 - -124: see <asm-sh/errno.h> */
+#include <linux/err.h>
+
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO:
+ * see <asm-sh/errno.h> */
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-124)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
        /* Avoid using "res" which is declared to be in register r0; \
           errno might expand to a function call and clobber it.  */ \
                int __err = -(res); \
@@ -444,6 +470,7 @@ __syscall_return(type,__sc0); \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
 #ifdef __KERNEL_SYSCALLS__
 
similarity index 99%
rename from include/asm-sh/rts7751r2d/voyagergx_reg.h
rename to include/asm-sh/voyagergx.h
index f031b5d6cf54b4681fd96366755afb661f56e2b7..99b0807d1c9f4806c1c51f3c4448fce433704828 100644 (file)
@@ -1,5 +1,5 @@
 /* -------------------------------------------------------------------- */
-/* voyagergx_reg.h                                                      */
+/* voyagergx.h                                                       */
 /* -------------------------------------------------------------------- */
 /*  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 09ca41972a11ce49d091fdc52d672a4e48e9af81..d19ea62ef8c674c953c5e89cdd62c75359778f5a 100644 (file)
@@ -62,7 +62,6 @@
 
 /**
  *     sh_wdt_read_cnt - Read from Counter
- *
  *     Reads back the WTCNT value.
  */
 static inline __u8 sh_wdt_read_cnt(void)
@@ -72,7 +71,6 @@ static inline __u8 sh_wdt_read_cnt(void)
 
 /**
  *     sh_wdt_write_cnt - Write to Counter
- *
  *     @val: Value to write
  *
  *     Writes the given value @val to the lower byte of the timer counter.
@@ -95,7 +93,6 @@ static inline __u8 sh_wdt_read_csr(void)
 
 /**
  *     sh_wdt_write_csr - Write to Control/Status Register
- *
  *     @val: Value to write
  *
  *     Writes the given value @val to the lower byte of the control/status
index 9a1590fffc1533d86ef6f1c670df551b7874f4d4..c113566bef3320b348f337a684688323b3e723f6 100644 (file)
 #ifdef __KERNEL__ 
 
 #define NR_syscalls 321
+#include <linux/err.h>
 
-/* user-visible error numbers are in the range -1 - -125: see <asm-sh64/errno.h> */
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO:
+ * see <asm-sh64/errno.h> */
 
 #define __syscall_return(type, res) \
 do { \
@@ -358,7 +360,7 @@ do { \
        **       life easier in the system call epilogue (see entry.S)      \
        */                                                                  \
         register unsigned long __sr2 __asm__ ("r2") = res;                 \
-       if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) {          \
                errno = -(res);                                             \
                __sr2 = -1;                                                 \
        } \
diff --git a/include/asm-um/alternative-asm.i b/include/asm-um/alternative-asm.i
new file mode 100644 (file)
index 0000000..cae9fac
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __UM_ALTERNATIVE_ASM_I
+#define __UM_ALTERNATIVE_ASM_I
+
+#include "asm/arch/alternative-asm.i"
+
+#endif
diff --git a/include/asm-um/frame.i b/include/asm-um/frame.i
new file mode 100644 (file)
index 0000000..09d5dca
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __UM_FRAME_I
+#define __UM_FRAME_I
+
+#include "asm/arch/frame.i"
+
+#endif
index afa4fe1ca9f13eaba82ebd9b33df0602e47ca022..d99bbddffdb99781730f50d66155abf80d80afc1 100644 (file)
@@ -13,6 +13,7 @@ struct task_struct;
 #include "asm/ptrace.h"
 #include "choose-mode.h"
 #include "registers.h"
+#include "sysdep/archsetjmp.h"
 
 struct mm_struct;
 
@@ -43,8 +44,7 @@ struct thread_struct {
 #endif
 #ifdef CONFIG_MODE_SKAS
                struct {
-                       void *switch_buf;
-                       void *fork_buf;
+                       jmp_buf switch_buf;
                        int mm_count;
                } skas;
 #endif
@@ -138,7 +138,7 @@ extern struct cpuinfo_um cpu_data[];
 
 #ifdef CONFIG_MODE_SKAS
 #define KSTK_REG(tsk, reg) \
-       get_thread_reg(reg, tsk->thread.mode.skas.switch_buf)
+       get_thread_reg(reg, &tsk->thread.mode.skas.switch_buf)
 #else
 #define KSTK_REG(tsk, reg) (0xbadbabe)
 #endif
index 2074483e6ca4a2b9306234131bbea080c77dd309..03b4af4ac09a3c82509e93dc835ee84bb7f7d111 100644 (file)
 
 #define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64
 
+/* Also defined in sysdep/ptrace.h, so may already be defined. */
+#ifndef FS_BASE
 #define FS_BASE (21 * sizeof(unsigned long))
 #define GS_BASE (22 * sizeof(unsigned long))
 #define DS (23 * sizeof(unsigned long))
 #define ES (24 * sizeof(unsigned long))
 #define FS (25 * sizeof(unsigned long))
 #define GS (26 * sizeof(unsigned long))
+#endif
 
 #define PT_REGS_RBX(r) UPT_RBX(&(r)->regs)
 #define PT_REGS_RCX(r) UPT_RCX(&(r)->regs)
index bcb44bfe577a58c257b22d591ce9840427e74821..552b7c873a5702790d913ed85a4270baa4b3455e 100644 (file)
 #ifdef __KERNEL__
 
 #include <asm/clinkage.h>
+#include <linux/err.h>
 
 #define __syscall_return(type, res)                                          \
   do {                                                                       \
-         /* user-visible error numbers are in the range -1 - -124:           \
+         /* user-visible error numbers are in the range -1 - -MAX_ERRNO:      \
             see <asm-v850/errno.h> */                                        \
-         if (__builtin_expect ((unsigned long)(res) >= (unsigned long)(-125), 0)) { \
+         if (__builtin_expect ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO), 0)) { \
                  errno = -(res);                                             \
                  res = -1;                                                   \
          }                                                                   \
index 2c95a319c0566463df1d3a800c094564f87d0d1f..ed59aa4c6ff9c194f0b8a8ca66118d096876090a 100644 (file)
@@ -155,8 +155,6 @@ extern void acpi_reserve_bootmem(void);
 
 #endif /*CONFIG_ACPI_SLEEP*/
 
-#define boot_cpu_physical_apicid boot_cpu_id
-
 extern int acpi_disabled;
 extern int acpi_pci_disabled;
 
diff --git a/include/asm-x86_64/alternative-asm.i b/include/asm-x86_64/alternative-asm.i
new file mode 100644 (file)
index 0000000..e4041f4
--- /dev/null
@@ -0,0 +1,14 @@
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+       .macro LOCK_PREFIX
+1:     lock
+       .section .smp_locks,"a"
+       .align 8
+       .quad 1b
+       .previous
+       .endm
+#else
+       .macro LOCK_PREFIX
+       .endm
+#endif
index 9c96a0a8d1bd3c07f4e600e180135e7c7e12e8a4..9e66d32330c9d5a5371fb3b6e59f709cf7ac67eb 100644 (file)
@@ -17,6 +17,8 @@
 
 extern int apic_verbosity;
 extern int apic_runs_main_timer;
+extern int ioapic_force;
+extern int apic_mapped;
 
 /*
  * Define the default level of output to be very little
@@ -29,8 +31,6 @@ extern int apic_runs_main_timer;
                        printk(s, ##a);    \
        } while (0)
 
-#ifdef CONFIG_X86_LOCAL_APIC
-
 struct pt_regs;
 
 /*
@@ -95,17 +95,12 @@ extern void setup_APIC_extened_lvt(unsigned char lvt_off, unsigned char vector,
 #define K8_APIC_EXT_INT_MSG_EXT 0x7
 #define K8_APIC_EXT_LVT_ENTRY_THRESHOLD    0
 
-extern int disable_timer_pin_1;
-
-
 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
 
-#endif /* CONFIG_X86_LOCAL_APIC */
-
 extern unsigned boot_cpu_id;
 
 #endif /* __ASM_APIC_H */
index f7ba57b1cc08589a3516bab9d91ba82c67ad8d5b..5b535eaf5309b08252097cbcb630fb6afee89a72 100644 (file)
@@ -399,6 +399,8 @@ static __inline__ int fls(int x)
        return r+1;
 }
 
+#define ARCH_HAS_FAST_MULTIPLIER 1
+
 #include <asm-generic/bitops/hweight.h>
 
 #endif /* __KERNEL__ */
index 4e3919524240b66b1d26b02a9df1bde18d0ca346..6b93f5a3a5c8ee81eff80cf96ed40653338f58ed 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef _ASM_X86_64_CALGARY_H
 #define _ASM_X86_64_CALGARY_H
 
-#include <linux/config.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
@@ -34,12 +33,12 @@ struct iommu_table {
        unsigned long  it_base;      /* mapped address of tce table */
        unsigned long  it_hint;      /* Hint for next alloc */
        unsigned long *it_map;       /* A simple allocation bitmap for now */
+       void __iomem  *bbar;         /* Bridge BAR */
+       u64            tar_val;      /* Table Address Register */
+       struct timer_list watchdog_timer;
        spinlock_t     it_lock;      /* Protects it_map */
        unsigned int   it_size;      /* Size of iommu table in entries */
        unsigned char  it_busno;     /* Bus number this table belongs to */
-       void __iomem  *bbar;
-       u64            tar_val;
-       struct timer_list watchdog_timer;
 };
 
 #define TCE_TABLE_SIZE_UNSPECIFIED     ~0
index 0744db777676033aa351c41b7b64ebf0bdc4cd25..eedc08526b0b6d435d78626cb859156c51128677 100644 (file)
@@ -13,7 +13,7 @@
    away for older version. 
  */
 
-#ifdef CONFIG_UNWIND_INFO
+#ifdef CONFIG_AS_CFI
 
 #define CFI_STARTPROC .cfi_startproc
 #define CFI_ENDPROC .cfi_endproc
 #define CFI_REMEMBER_STATE .cfi_remember_state
 #define CFI_RESTORE_STATE .cfi_restore_state
 #define CFI_UNDEFINED .cfi_undefined
+#ifdef CONFIG_AS_CFI_SIGNAL_FRAME
+#define CFI_SIGNAL_FRAME .cfi_signal_frame
+#else
+#define CFI_SIGNAL_FRAME
+#endif
 
 #else
 
@@ -45,6 +50,7 @@
 #define CFI_REMEMBER_STATE     #
 #define CFI_RESTORE_STATE      #
 #define CFI_UNDEFINED  #
+#define CFI_SIGNAL_FRAME       #
 
 #endif
 
index f65674832318b8e7311ce995a32591f9711ca9d1..fa2086774105500f5ac2d7a5f8e1a6bbef219d38 100644 (file)
 
 #define E820_RAM       1
 #define E820_RESERVED  2
-#define E820_ACPI      3 /* usable as RAM once ACPI tables have been read */
+#define E820_ACPI      3
 #define E820_NVS       4
 
-#define HIGH_MEMORY    (1024*1024)
-
-#define LOWMEMSIZE()   (0x9f000)
-
 #ifndef __ASSEMBLY__
 struct e820entry {
        u64 addr;       /* start of memory segment */
@@ -51,13 +47,11 @@ 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 void e820_bootmem_free(pg_data_t *pgdat, unsigned long start,unsigned long end);
 extern void e820_setup_gap(void);
-extern unsigned long e820_hole_size(unsigned long start_pfn,
-                                   unsigned long end_pfn);
+extern void e820_register_active_regions(int nid,
+                               unsigned long start_pfn, unsigned long end_pfn);
 
-extern void __init parse_memopt(char *p, char **end);
-extern void __init parse_memmapopt(char *p, char **end);
+extern void finish_e820_parsing(void);
 
 extern struct e820map e820;
 
index 0b4ffbd1a12521a2fab5be65938f87f3348a1004..1b620db5b9e3db21d9c1fef19f435b3fdc09cac4 100644 (file)
@@ -37,13 +37,9 @@ enum fixed_addresses {
        VSYSCALL_FIRST_PAGE = VSYSCALL_LAST_PAGE + ((VSYSCALL_END-VSYSCALL_START) >> PAGE_SHIFT) - 1,
        VSYSCALL_HPET,
        FIX_HPET_BASE,
-#ifdef CONFIG_X86_LOCAL_APIC
        FIX_APIC_BASE,  /* local (CPU) APIC) -- required for SMP or not */
-#endif
-#ifdef CONFIG_X86_IO_APIC
        FIX_IO_APIC_BASE_0,
        FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1,
-#endif
        __end_of_fixed_addresses
 };
 
index 50b38e7c58e4f5fa226dacbb9df86459d48a7978..81e714665344623c9990199a5faaee15261b397b 100644 (file)
@@ -16,7 +16,6 @@ struct genapic {
        char *name;
        u32 int_delivery_mode;
        u32 int_dest_mode;
-       u32 int_delivery_dest;  /* for quick IPIs */
        int (*apic_id_registered)(void);
        cpumask_t (*target_cpus)(void);
        void (*init_apic_ldr)(void);
index cba8a3b0cded5a77191d9528710b04c85bc13c5b..0217b74cc9fc0cd30456d40929e6196229680178 100644 (file)
@@ -24,6 +24,7 @@ extern unsigned int mxcsr_feature_mask;
 extern void mxcsr_feature_mask_init(void);
 extern void init_fpu(struct task_struct *child);
 extern int save_i387(struct _fpstate __user *buf);
+extern asmlinkage void math_state_restore(void);
 
 /*
  * FPU lazy state save handling...
@@ -31,7 +32,9 @@ extern int save_i387(struct _fpstate __user *buf);
 
 #define unlazy_fpu(tsk) do { \
        if (task_thread_info(tsk)->status & TS_USEDFPU) \
-               save_init_fpu(tsk); \
+               save_init_fpu(tsk);                     \
+       else                                            \
+               tsk->fpu_counter = 0;                   \
 } while (0)
 
 /* Ignore delayed exceptions from user space */
@@ -134,8 +137,8 @@ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
 #else
                     : [fx] "cdaSDb" (fx), "0" (0));
 #endif
-       if (unlikely(err))
-               __clear_user(fx, sizeof(struct i387_fxsave_struct));
+       if (unlikely(err) && __clear_user(fx, sizeof(struct i387_fxsave_struct)))
+               err = -EFAULT;
        /* No need to clear here because the caller clears USED_MATH */
        return err;
 } 
index 59c39643156910294a0fee24bf2d048f5d98b72f..8633331420ece5b8ae9d4650999b3651b79edf28 100644 (file)
 
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL  (0x3c)
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK        (0x00 << 8)
-#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT (1 << 0)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX (0)
+#define ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT \
+                               (1 << (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX))
+
+union cpuid10_eax {
+       struct {
+               unsigned int version_id:8;
+               unsigned int num_counters:8;
+               unsigned int bit_width:8;
+               unsigned int mask_length:8;
+       } split;
+       unsigned int full;
+};
 
 #endif /* X86_64_INTEL_ARCH_PERFMON_H */
index fb7a0909a17417778eaa659da883f488ab324f61..5d1b5c68e36efaf005a3e06408a220249c1f0527 100644 (file)
@@ -10,8 +10,6 @@
  * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar
  */
 
-#ifdef CONFIG_X86_IO_APIC
-
 #ifdef CONFIG_PCI_MSI
 static inline int use_pci_vector(void) {return 1;}
 static inline void disable_edge_ioapic_vector(unsigned int vector) { }
@@ -209,10 +207,6 @@ extern int timer_uses_ioapic_pin_0;
 
 extern int sis_apic_bug; /* dummy */ 
 
-#else  /* !CONFIG_X86_IO_APIC */
-#define io_apic_assign_pci_irqs 0
-#endif
-
 extern int assign_irq_vector(int irq);
 
 void enable_NMI_through_LVT0 (void * dummy);
index 9db5a1b4f7b11c4602fbc2f208b1c655ac087ebe..43469d8ab71a2534c91d4c80ccae2f0f3cae2563 100644 (file)
@@ -44,9 +44,7 @@ static __inline__ int irq_canonicalize(int irq)
        return ((irq == 2) ? 9 : irq);
 }
 
-#ifdef CONFIG_X86_LOCAL_APIC
 #define ARCH_HAS_NMI_WATCHDOG          /* See include/linux/nmi.h */
-#endif
 
 #ifdef CONFIG_HOTPLUG_CPU
 #include <linux/cpumask.h>
index c564bae034338272e952c05fb84646b9b60a669f..5fab957e10918425044a760578030632d478ac87 100644 (file)
@@ -1,6 +1,27 @@
 #ifndef _X86_64_KEXEC_H
 #define _X86_64_KEXEC_H
 
+#define PA_CONTROL_PAGE  0
+#define VA_CONTROL_PAGE  1
+#define PA_PGD           2
+#define VA_PGD           3
+#define PA_PUD_0         4
+#define VA_PUD_0         5
+#define PA_PMD_0         6
+#define VA_PMD_0         7
+#define PA_PTE_0         8
+#define VA_PTE_0         9
+#define PA_PUD_1         10
+#define VA_PUD_1         11
+#define PA_PMD_1         12
+#define VA_PMD_1         13
+#define PA_PTE_1         14
+#define VA_PTE_1         15
+#define PA_TABLE_PAGE    16
+#define PAGES_NR         17
+
+#ifndef __ASSEMBLY__
+
 #include <linux/string.h>
 
 #include <asm/page.h>
@@ -64,4 +85,12 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
                newregs->rip = (unsigned long)current_text_addr();
        }
 }
+
+NORET_TYPE void
+relocate_kernel(unsigned long indirection_page,
+               unsigned long page_list,
+               unsigned long start_address) ATTRIB_NORET;
+
+#endif /* __ASSEMBLY__ */
+
 #endif /* _X86_64_KEXEC_H */
index 291c2d01c44f29dad20f7623783b8bad362eaddf..b5f39d0189ce0d01191ac14809a3caeae2bcf85d 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef __ASM_LINKAGE_H
 #define __ASM_LINKAGE_H
 
-/* Nothing to see here... */
+#define __ALIGN .p2align 4,,15
 
 #endif
index 0acea44c93775f69d00cfcf96a228b9cf157cdda..d33422450c00a3bc677246c1cd561ac425e00ad5 100644 (file)
@@ -16,7 +16,6 @@
 
 #define INT_DELIVERY_MODE (genapic->int_delivery_mode)
 #define INT_DEST_MODE (genapic->int_dest_mode)
-#define INT_DELIVERY_DEST (genapic->int_delivery_dest)
 #define TARGET_CPUS      (genapic->target_cpus())
 #define apic_id_registered (genapic->apic_id_registered)
 #define init_apic_ldr (genapic->init_apic_ldr)
index d13687dfd691752400dc6ed82bd3754dfa52d5c5..5a11146d6d9cc753f6eb82face2fb15aba39c9c6 100644 (file)
@@ -99,6 +99,8 @@ static inline void mce_amd_feature_init(struct cpuinfo_x86 *c)
 }
 #endif
 
+void mce_log_therm_throt_event(unsigned int cpu, __u64 status);
+
 extern atomic_t mce_entry;
 
 #endif
diff --git a/include/asm-x86_64/mmx.h b/include/asm-x86_64/mmx.h
deleted file mode 100644 (file)
index 46b71da..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _ASM_MMX_H
-#define _ASM_MMX_H
-
-/*
- *     MMX 3Dnow! helper operations
- */
-
-#include <linux/types.h>
-extern void *_mmx_memcpy(void *to, const void *from, size_t size);
-extern void mmx_clear_page(void *page);
-extern void mmx_copy_page(void *to, void *from);
-
-#endif
index 14fc3ddd90310044019cbc707bda621fad3c87ad..017fddb61dc52e95472fc3654cdb10508a3d19ea 100644 (file)
@@ -159,13 +159,7 @@ struct mpc_config_lintsrc
 #define MAX_MP_BUSSES 256
 /* Each PCI slot may be a combo card with its own bus.  4 IRQ pins per slot. */
 #define MAX_IRQ_SOURCES (MAX_MP_BUSSES * 4)
-enum mp_bustype {
-       MP_BUS_ISA = 1,
-       MP_BUS_EISA,
-       MP_BUS_PCI,
-       MP_BUS_MCA
-};
-extern unsigned char mp_bus_id_to_type [MAX_MP_BUSSES];
+extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
 extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
 
 extern unsigned int boot_cpu_physical_apicid;
@@ -178,18 +172,15 @@ extern int mp_irq_entries;
 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;
 
 #ifdef CONFIG_ACPI
 extern void mp_register_lapic (u8 id, u8 enabled);
 extern void mp_register_lapic_address (u64 address);
 
-#ifdef CONFIG_X86_IO_APIC
 extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
 extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi);
 extern void mp_config_acpi_legacy_irqs (void);
 extern int mp_register_gsi (u32 gsi, int triggering, int polarity);
-#endif /*CONFIG_X86_IO_APIC*/
 #endif
 
 extern int using_apic_timer;
index 10f8b51cec8ba3e76dadcfd74a3955d7c7e350ba..37e194169fac2f2793894331eb9ec34d81401dfa 100644 (file)
 #define rdtscl(low) \
      __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx")
 
+#define rdtscp(low,high,aux) \
+     asm volatile (".byte 0x0f,0x01,0xf9" : "=a" (low), "=d" (high), "=c" (aux))
+
 #define rdtscll(val) do { \
      unsigned int __a,__d; \
      asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
      (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
 } while(0)
 
+#define rdtscpll(val, aux) do { \
+     unsigned long __a, __d; \
+     asm volatile (".byte 0x0f,0x01,0xf9" : "=a" (__a), "=d" (__d), "=c" (aux)); \
+     (val) = (__d << 32) | __a; \
+} while (0)
+
 #define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
 
+#define write_rdtscp_aux(val) wrmsr(0xc0000103, val, 0)
+
 #define rdpmc(counter,low,high) \
      __asm__ __volatile__("rdpmc" \
                          : "=a" (low), "=d" (high) \
index 06fab6de2a88bc7395a9f68a76c502291b7e3e9d..16396b1de3e44e2068021f446d8b56f3b6f79448 100644 (file)
@@ -25,13 +25,9 @@ do {                                                                 \
                                                                        \
        __asm__ __volatile__(                                           \
                LOCK_PREFIX "   decl (%%rdi)    \n"                     \
-                       "   js 2f               \n"                     \
-                       "1:                     \n"                     \
-                                                                       \
-               LOCK_SECTION_START("")                                  \
-                       "2: call "#fail_fn"     \n"                     \
-                       "   jmp 1b              \n"                     \
-               LOCK_SECTION_END                                        \
+                       "   jns 1f              \n"                     \
+                       "   call "#fail_fn"     \n"                     \
+                       "1:"                                            \
                                                                        \
                :"=D" (dummy)                                           \
                : "D" (v)                                               \
@@ -75,13 +71,9 @@ do {                                                                 \
                                                                        \
        __asm__ __volatile__(                                           \
                LOCK_PREFIX "   incl (%%rdi)    \n"                     \
-                       "   jle 2f              \n"                     \
-                       "1:                     \n"                     \
-                                                                       \
-               LOCK_SECTION_START("")                                  \
-                       "2: call "#fail_fn"     \n"                     \
-                       "   jmp 1b              \n"                     \
-               LOCK_SECTION_END                                        \
+                       "   jg 1f               \n"                     \
+                       "   call "#fail_fn"     \n"                     \
+                       "1:                       "                     \
                                                                        \
                :"=D" (dummy)                                           \
                : "D" (v)                                               \
index efb45c894d7604ff89b92e35ddf12091636e634f..cbf2669bca71505013227528f9f779c87c81492a 100644 (file)
@@ -7,24 +7,13 @@
 #include <linux/pm.h>
 #include <asm/io.h>
  
-struct pt_regs;
-
-typedef int (*nmi_callback_t)(struct pt_regs * regs, int cpu);
-
-/**
- * set_nmi_callback
- *
- * Set a handler for an NMI. Only one handler may be
- * set. Return 1 if the NMI was handled.
- */
-void set_nmi_callback(nmi_callback_t callback);
-
 /**
- * unset_nmi_callback
+ * do_nmi_callback
  *
- * Remove the handler previously set.
+ * Check to see if a callback exists and execute it.  Return 1
+ * if the handler exists and was handled successfully.
  */
-void unset_nmi_callback(void);
+int do_nmi_callback(struct pt_regs *regs, int cpu);
 
 #ifdef CONFIG_PM
  
@@ -48,25 +37,32 @@ static inline void unset_nmi_pm_callback(struct pm_dev * dev)
 #endif /* CONFIG_PM */
  
 extern void default_do_nmi(struct pt_regs *);
-extern void die_nmi(char *str, struct pt_regs *regs);
+extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
 
 #define get_nmi_reason() inb(0x61)
 
 extern int panic_on_timeout;
 extern int unknown_nmi_panic;
+extern int nmi_watchdog_enabled;
 
 extern int check_nmi_watchdog(void);
-extern void setup_apic_nmi_watchdog (void);
-extern int reserve_lapic_nmi(void);
-extern void release_lapic_nmi(void);
+extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
+extern int avail_to_resrv_perfctr_nmi(unsigned int);
+extern int reserve_perfctr_nmi(unsigned int);
+extern void release_perfctr_nmi(unsigned int);
+extern int reserve_evntsel_nmi(unsigned int);
+extern void release_evntsel_nmi(unsigned int);
+
+extern void setup_apic_nmi_watchdog (void *);
+extern void stop_apic_nmi_watchdog (void *);
 extern void disable_timer_nmi_watchdog(void);
 extern void enable_timer_nmi_watchdog(void);
-extern void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
+extern int nmi_watchdog_tick (struct pt_regs * regs, unsigned reason);
 
 extern void nmi_watchdog_default(void);
 extern int setup_nmi_watchdog(char *);
 
+extern atomic_t nmi_active;
 extern unsigned int nmi_watchdog;
 #define NMI_DEFAULT    -1
 #define NMI_NONE       0
index 036b6ca5b53bb6b147bfac8874bfd20011d628bf..eba9cb471df38b1bee0b4893482fccb576411795 100644 (file)
@@ -2,47 +2,15 @@
 #define ASM_PCI_DIRECT_H 1
 
 #include <linux/types.h>
-#include <asm/io.h>
 
 /* Direct PCI access. This is used for PCI accesses in early boot before
    the PCI subsystem works. */ 
 
-#define PDprintk(x...)
+extern u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset);
+extern u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset);
+extern u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset);
+extern void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset, u32 val);
 
-static inline u32 read_pci_config(u8 bus, u8 slot, u8 func, u8 offset)
-{
-       u32 v; 
-       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
-       v = inl(0xcfc); 
-       if (v != 0xffffffff)
-               PDprintk("%x reading 4 from %x: %x\n", slot, offset, v);
-       return v;
-}
-
-static inline u8 read_pci_config_byte(u8 bus, u8 slot, u8 func, u8 offset)
-{
-       u8 v; 
-       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
-       v = inb(0xcfc + (offset&3)); 
-       PDprintk("%x reading 1 from %x: %x\n", slot, offset, v);
-       return v;
-}
-
-static inline u16 read_pci_config_16(u8 bus, u8 slot, u8 func, u8 offset)
-{
-       u16 v; 
-       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
-       v = inw(0xcfc + (offset&2)); 
-       PDprintk("%x reading 2 from %x: %x\n", slot, offset, v);
-       return v;
-}
-
-static inline void write_pci_config(u8 bus, u8 slot, u8 func, u8 offset,
-                                   u32 val)
-{
-       PDprintk("%x writing to %x: %x\n", slot, offset, val); 
-       outl(0x80000000 | (bus<<16) | (slot<<11) | (func<<8) | offset, 0xcf8);
-       outl(val, 0xcfc); 
-}
+extern int early_pci_allowed(void);
 
 #endif
index b47c3df9ed1dd72d792ceca2e6f8f5d6338b7556..14996d962bac782bb67c809a571647d16e5b16cb 100644 (file)
@@ -9,20 +9,24 @@
 
 /* Per processor datastructure. %gs points to it while the kernel runs */ 
 struct x8664_pda {
-       struct task_struct *pcurrent;   /* Current process */
-       unsigned long data_offset;      /* Per cpu data offset from linker address */
-       unsigned long kernelstack;  /* top of kernel stack for current */ 
-       unsigned long oldrsp;       /* user rsp for system call */
-#if DEBUG_STKSZ > EXCEPTION_STKSZ
-       unsigned long debugstack;   /* #DB/#BP stack. */
+       struct task_struct *pcurrent;   /* 0  Current process */
+       unsigned long data_offset;      /* 8 Per cpu data offset from linker
+                                          address */
+       unsigned long kernelstack;  /* 16 top of kernel stack for current */
+       unsigned long oldrsp;       /* 24 user rsp for system call */
+        int irqcount;              /* 32 Irq nesting counter. Starts with -1 */
+       int cpunumber;              /* 36 Logical CPU number */
+#ifdef CONFIG_CC_STACKPROTECTOR
+       unsigned long stack_canary;     /* 40 stack canary value */
+                                       /* gcc-ABI: this canary MUST be at
+                                          offset 40!!! */
 #endif
-        int irqcount;              /* Irq nesting counter. Starts with -1 */   
-       int cpunumber;              /* Logical CPU number */
-       char *irqstackptr;      /* top of irqstack */
+       char *irqstackptr;
        int nodenumber;             /* number of current node */
        unsigned int __softirq_pending;
        unsigned int __nmi_count;       /* number of NMI on this CPUs */
-       int mmu_state;     
+       short mmu_state;
+       short isidle;
        struct mm_struct *active_mm;
        unsigned apic_timer_irqs;
 } ____cacheline_aligned_in_smp;
@@ -36,44 +40,69 @@ extern struct x8664_pda boot_cpu_pda[];
  * There is no fast way to get the base address of the PDA, all the accesses
  * have to mention %fs/%gs.  So it needs to be done this Torvaldian way.
  */ 
-#define sizeof_field(type,field)  (sizeof(((type *)0)->field))
-#define typeof_field(type,field)  typeof(((type *)0)->field)
+extern void __bad_pda_field(void) __attribute__((noreturn));
 
-extern void __bad_pda_field(void);
+/*
+ * proxy_pda doesn't actually exist, but tell gcc it is accessed for
+ * all PDA accesses so it gets read/write dependencies right.
+ */
+extern struct x8664_pda _proxy_pda;
 
 #define pda_offset(field) offsetof(struct x8664_pda, field)
 
-#define pda_to_op(op,field,val) do { \
-       typedef typeof_field(struct x8664_pda, field) T__; \
-       switch (sizeof_field(struct x8664_pda, field)) {                \
-case 2: \
-asm volatile(op "w %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
-case 4: \
-asm volatile(op "l %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
-case 8: \
-asm volatile(op "q %0,%%gs:%P1"::"ri" ((T__)val),"i"(pda_offset(field)):"memory"); break; \
-       default: __bad_pda_field();                                     \
-       } \
+#define pda_to_op(op,field,val) do {           \
+       typedef typeof(_proxy_pda.field) T__;   \
+       if (0) { T__ tmp__; tmp__ = (val); }    /* type checking */ \
+       switch (sizeof(_proxy_pda.field)) {     \
+       case 2:                                 \
+               asm(op "w %1,%%gs:%c2" :        \
+                   "+m" (_proxy_pda.field) :   \
+                   "ri" ((T__)val),            \
+                   "i"(pda_offset(field)));    \
+               break;                          \
+       case 4:                                 \
+               asm(op "l %1,%%gs:%c2" :        \
+                   "+m" (_proxy_pda.field) :   \
+                   "ri" ((T__)val),            \
+                   "i" (pda_offset(field)));   \
+               break;                          \
+       case 8:                                 \
+               asm(op "q %1,%%gs:%c2":         \
+                   "+m" (_proxy_pda.field) :   \
+                   "ri" ((T__)val),            \
+                   "i"(pda_offset(field)));    \
+               break;                          \
+       default:                                \
+               __bad_pda_field();              \
+       }                                       \
        } while (0)
 
-/* 
- * AK: PDA read accesses should be neither volatile nor have an memory clobber.
- * Unfortunately removing them causes all hell to break lose currently.
- */
-#define pda_from_op(op,field) ({ \
-       typeof_field(struct x8664_pda, field) ret__; \
-       switch (sizeof_field(struct x8664_pda, field)) {                \
-case 2: \
-asm volatile(op "w %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\
-case 4: \
-asm volatile(op "l %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\
-case 8: \
-asm volatile(op "q %%gs:%P1,%0":"=r" (ret__):"i"(pda_offset(field)):"memory"); break;\
-       default: __bad_pda_field();                                     \
-       } \
+#define pda_from_op(op,field) ({               \
+       typeof(_proxy_pda.field) ret__;         \
+       switch (sizeof(_proxy_pda.field)) {     \
+               case 2:                                 \
+               asm(op "w %%gs:%c1,%0" :        \
+                   "=r" (ret__) :              \
+                   "i" (pda_offset(field)),    \
+                   "m" (_proxy_pda.field));    \
+                break;                         \
+       case 4:                                 \
+               asm(op "l %%gs:%c1,%0":         \
+                   "=r" (ret__):               \
+                   "i" (pda_offset(field)),    \
+                   "m" (_proxy_pda.field));    \
+                break;                         \
+       case 8:                                 \
+               asm(op "q %%gs:%c1,%0":         \
+                   "=r" (ret__) :              \
+                   "i" (pda_offset(field)),    \
+                   "m" (_proxy_pda.field));    \
+                break;                         \
+       default:                                \
+               __bad_pda_field();              \
+       }                                       \
        ret__; })
 
-
 #define read_pda(field) pda_from_op("mov",field)
 #define write_pda(field,val) pda_to_op("mov",field,val)
 #define add_pda(field,val) pda_to_op("add",field,val)
index bffb2f886a510256974c679095186af021537c3c..285756010c517ed2dbc3a9e89e4abb2ac676f561 100644 (file)
 
 #include <asm/pda.h>
 
+#ifdef CONFIG_MODULES
+# define PERCPU_MODULE_RESERVE 8192
+#else
+# define PERCPU_MODULE_RESERVE 0
+#endif
+
+#define PERCPU_ENOUGH_ROOM \
+       (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \
+        PERCPU_MODULE_RESERVE)
+
 #define __per_cpu_offset(cpu) (cpu_pda(cpu)->data_offset)
 #define __my_cpu_offset() read_pda(data_offset)
 
index 51eba239517194df544570cca0869b16dad6a1c1..6899e770b173e4a2cb75fdd5bc664359cdf0fa7b 100644 (file)
@@ -21,12 +21,9 @@ extern unsigned long __supported_pte_mask;
 
 #define swapper_pg_dir init_level4_pgt
 
-extern int nonx_setup(char *str);
 extern void paging_init(void);
 extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
 
-extern unsigned long pgkern_mask;
-
 /*
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
@@ -265,7 +262,7 @@ static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot)
 #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
 static inline int pte_user(pte_t pte)          { return pte_val(pte) & _PAGE_USER; }
 static inline int pte_read(pte_t pte)          { return pte_val(pte) & _PAGE_USER; }
-static inline int pte_exec(pte_t pte)          { return pte_val(pte) & _PAGE_USER; }
+static inline int pte_exec(pte_t pte)          { return !(pte_val(pte) & _PAGE_NX); }
 static inline int pte_dirty(pte_t pte)         { return pte_val(pte) & _PAGE_DIRTY; }
 static inline int pte_young(pte_t pte)         { return pte_val(pte) & _PAGE_ACCESSED; }
 static inline int pte_write(pte_t pte)         { return pte_val(pte) & _PAGE_RW; }
@@ -278,11 +275,12 @@ static inline pte_t pte_mkclean(pte_t pte)        { set_pte(&pte, __pte(pte_val(pte) &
 static inline pte_t pte_mkold(pte_t pte)       { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
 static inline pte_t pte_wrprotect(pte_t pte)   { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; }
 static inline pte_t pte_mkread(pte_t pte)      { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
-static inline pte_t pte_mkexec(pte_t pte)      { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
+static inline pte_t pte_mkexec(pte_t pte)      { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_NX)); return pte; }
 static inline pte_t pte_mkdirty(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
 static inline pte_t pte_mkhuge(pte_t pte)      { set_pte(&pte, __pte(pte_val(pte) | _PAGE_PSE)); return pte; }
+static inline pte_t pte_clrhuge(pte_t pte)     { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_PSE)); return pte; }
 
 struct vm_area_struct;
 
index 038fe1f47e6fcb5804a5878270614289f545d9d4..c28fc2db217197e30a99b956aaa523aaefe4bc9b 100644 (file)
@@ -24,8 +24,6 @@ extern void mtrr_bp_init(void);
 #define mtrr_bp_init() do {} while (0)
 #endif
 extern void init_memory_mapping(unsigned long start, unsigned long end);
-extern void size_zones(unsigned long *z, unsigned long *h,
-                       unsigned long start_pfn, unsigned long end_pfn);
 
 extern void system_call(void); 
 extern int kernel_syscall(void);
@@ -51,10 +49,8 @@ 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 int numa_setup(char *opt);
-
-extern int setup_early_printk(char *); 
 extern void early_printk(const char *fmt, ...) __attribute__((format(printf,1,2)));
 
 extern void early_identify_cpu(struct cpuinfo_x86 *c);
@@ -91,7 +87,7 @@ extern void syscall32_cpu_init(void);
 
 extern void setup_node_bootmem(int nodeid, unsigned long start, unsigned long end);
 
-extern void check_ioapic(void);
+extern void early_quirks(void);
 extern void check_efer(void);
 
 extern int unhandled_signal(struct task_struct *tsk, int sig);
@@ -103,13 +99,7 @@ extern void select_idle_routine(const struct cpuinfo_x86 *c);
 extern unsigned long table_start, table_end;
 
 extern int exception_trace;
-extern int using_apic_timer;
-extern int disable_apic;
 extern unsigned cpu_khz;
-extern int ioapic_force;
-extern int skip_ioapic_setup;
-extern int acpi_ht;
-extern int acpi_disabled;
 
 extern void no_iommu_init(void);
 extern int force_iommu, no_iommu;
@@ -131,7 +121,8 @@ extern int fix_aperture;
 
 extern int reboot_force;
 extern int notsc_setup(char *);
-extern int setup_additional_cpus(char *);
+
+extern int gsi_irq_sharing(int gsi);
 
 extern void smp_local_timer_interrupt(struct pt_regs * regs);
 
index dea0e94592641fbc12dbb9d175f74364d19010ec..72aeebed920b9fba3d49d6d3852fcc18adcc31d5 100644 (file)
 #ifndef _ASM_X86_64_RWLOCK_H
 #define _ASM_X86_64_RWLOCK_H
 
-#include <linux/stringify.h>
-
 #define RW_LOCK_BIAS            0x01000000
-#define RW_LOCK_BIAS_STR       "0x01000000"
-
-#define __build_read_lock_ptr(rw, helper)   \
-       asm volatile(LOCK_PREFIX "subl $1,(%0)\n\t" \
-                    "js 2f\n" \
-                    "1:\n" \
-                   LOCK_SECTION_START("") \
-                    "2:\tcall " helper "\n\t" \
-                    "jmp 1b\n" \
-                   LOCK_SECTION_END \
-                    ::"a" (rw) : "memory")
-
-#define __build_read_lock_const(rw, helper)   \
-       asm volatile(LOCK_PREFIX "subl $1,%0\n\t" \
-                    "js 2f\n" \
-                    "1:\n" \
-                   LOCK_SECTION_START("") \
-                    "2:\tpushq %%rax\n\t" \
-                    "leaq %0,%%rax\n\t" \
-                    "call " helper "\n\t" \
-                    "popq %%rax\n\t" \
-                    "jmp 1b\n" \
-                   LOCK_SECTION_END \
-                    :"=m" (*((volatile int *)rw))::"memory")
-
-#define __build_read_lock(rw, helper)  do { \
-                                               if (__builtin_constant_p(rw)) \
-                                                       __build_read_lock_const(rw, helper); \
-                                               else \
-                                                       __build_read_lock_ptr(rw, helper); \
-                                       } while (0)
-
-#define __build_write_lock_ptr(rw, helper) \
-       asm volatile(LOCK_PREFIX "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
-                    "jnz 2f\n" \
-                    "1:\n" \
-                    LOCK_SECTION_START("") \
-                    "2:\tcall " helper "\n\t" \
-                    "jmp 1b\n" \
-                    LOCK_SECTION_END \
-                    ::"a" (rw) : "memory")
-
-#define __build_write_lock_const(rw, helper) \
-       asm volatile(LOCK_PREFIX "subl $" RW_LOCK_BIAS_STR ",%0\n\t" \
-                    "jnz 2f\n" \
-                    "1:\n" \
-                   LOCK_SECTION_START("") \
-                    "2:\tpushq %%rax\n\t" \
-                    "leaq %0,%%rax\n\t" \
-                    "call " helper "\n\t" \
-                    "popq %%rax\n\t" \
-                    "jmp 1b\n" \
-                   LOCK_SECTION_END \
-                    :"=m" (*((volatile long *)rw))::"memory")
+#define RW_LOCK_BIAS_STR        "0x01000000"
 
-#define __build_write_lock(rw, helper) do { \
-                                               if (__builtin_constant_p(rw)) \
-                                                       __build_write_lock_const(rw, helper); \
-                                               else \
-                                                       __build_write_lock_ptr(rw, helper); \
-                                       } while (0)
+/* Actual code is in asm/spinlock.h or in arch/x86_64/lib/rwlock.S */
 
 #endif
index d4bed33fb32c4ca56eed659843c974b3286fc052..334ddcdd8f92dd52e70f8240abf6edaf360ddfc2 100644 (file)
 #define __USER_CS     0x33   /* 6*8+3 */ 
 #define __USER32_DS    __USER_DS 
 
-#define GDT_ENTRY_TLS 1
 #define GDT_ENTRY_TSS 8        /* needs two entries */
 #define GDT_ENTRY_LDT 10 /* needs two entries */
 #define GDT_ENTRY_TLS_MIN 12
 #define GDT_ENTRY_TLS_MAX 14
-/* 15 free */
 
 #define GDT_ENTRY_TLS_ENTRIES 3
 
+#define GDT_ENTRY_PER_CPU 15   /* Abused to load per CPU data from limit */
+#define __PER_CPU_SEG  (GDT_ENTRY_PER_CPU * 8 + 3)
+
 /* TLS indexes for 64bit - hardcoded in arch_prctl */
 #define FS_TLS 0       
 #define GS_TLS 1       
index 064df08b9a0f039f24a3cd302d10b480d0341c62..107bd90429e86e14e47185895d9ab222be3b0652 100644 (file)
@@ -107,12 +107,9 @@ static inline void down(struct semaphore * sem)
        __asm__ __volatile__(
                "# atomic down operation\n\t"
                LOCK_PREFIX "decl %0\n\t"     /* --sem->count */
-               "js 2f\n"
-               "1:\n"
-               LOCK_SECTION_START("")
-               "2:\tcall __down_failed\n\t"
-               "jmp 1b\n"
-               LOCK_SECTION_END
+               "jns 1f\n\t"
+               "call __down_failed\n"
+               "1:"
                :"=m" (sem->count)
                :"D" (sem)
                :"memory");
@@ -130,14 +127,11 @@ static inline int down_interruptible(struct semaphore * sem)
 
        __asm__ __volatile__(
                "# atomic interruptible down operation\n\t"
+               "xorl %0,%0\n\t"
                LOCK_PREFIX "decl %1\n\t"     /* --sem->count */
-               "js 2f\n\t"
-               "xorl %0,%0\n"
-               "1:\n"
-               LOCK_SECTION_START("")
-               "2:\tcall __down_failed_interruptible\n\t"
-               "jmp 1b\n"
-               LOCK_SECTION_END
+               "jns 2f\n\t"
+               "call __down_failed_interruptible\n"
+               "2:\n"
                :"=a" (result), "=m" (sem->count)
                :"D" (sem)
                :"memory");
@@ -154,14 +148,11 @@ static inline int down_trylock(struct semaphore * sem)
 
        __asm__ __volatile__(
                "# atomic interruptible down operation\n\t"
+               "xorl %0,%0\n\t"
                LOCK_PREFIX "decl %1\n\t"     /* --sem->count */
-               "js 2f\n\t"
-               "xorl %0,%0\n"
-               "1:\n"
-               LOCK_SECTION_START("")
-               "2:\tcall __down_failed_trylock\n\t"
-               "jmp 1b\n"
-               LOCK_SECTION_END
+               "jns 2f\n\t"
+               "call __down_failed_trylock\n\t"
+               "2:\n"
                :"=a" (result), "=m" (sem->count)
                :"D" (sem)
                :"memory","cc");
@@ -179,12 +170,9 @@ static inline void up(struct semaphore * sem)
        __asm__ __volatile__(
                "# atomic up operation\n\t"
                LOCK_PREFIX "incl %0\n\t"     /* ++sem->count */
-               "jle 2f\n"
-               "1:\n"
-               LOCK_SECTION_START("")
-               "2:\tcall __up_wakeup\n\t"
-               "jmp 1b\n"
-               LOCK_SECTION_END
+               "jg 1f\n\t"
+               "call __up_wakeup\n"
+               "1:"
                :"=m" (sem->count)
                :"D" (sem)
                :"memory");
index 3ede2a61973a1d827411a939f481f162d86734c6..4581f978b299d79df12f274dbd7ad14b2ff35598 100644 (file)
@@ -24,10 +24,6 @@ typedef struct {
 } sigset_t;
 
 
-struct pt_regs; 
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
-
 #else
 /* Here we must cater to libcs that poke about in kernel headers.  */
 
index ce97f65e1d10f5312b1d49df136c21417e1fc033..d6b7c057edbaf281ddb97963e027e17931a01211 100644 (file)
@@ -4,27 +4,18 @@
 /*
  * We need the APIC definitions automatically as part of 'smp.h'
  */
-#ifndef __ASSEMBLY__
 #include <linux/threads.h>
 #include <linux/cpumask.h>
 #include <linux/bitops.h>
 extern int disable_apic;
-#endif
 
-#ifdef CONFIG_X86_LOCAL_APIC
-#ifndef __ASSEMBLY__
 #include <asm/fixmap.h>
 #include <asm/mpspec.h>
-#ifdef CONFIG_X86_IO_APIC
 #include <asm/io_apic.h>
-#endif
 #include <asm/apic.h>
 #include <asm/thread_info.h>
-#endif
-#endif
 
 #ifdef CONFIG_SMP
-#ifndef ASSEMBLY
 
 #include <asm/pda.h>
 
@@ -42,7 +33,6 @@ extern cpumask_t cpu_initialized;
  
 extern void smp_alloc_memory(void);
 extern volatile unsigned long smp_invalidate_needed;
-extern int pic_mode;
 extern void lock_ipi_call_lock(void);
 extern void unlock_ipi_call_lock(void);
 extern int smp_num_siblings;
@@ -74,20 +64,16 @@ static inline int hard_smp_processor_id(void)
        return GET_APIC_ID(*(unsigned int *)(APIC_BASE+APIC_ID));
 }
 
-extern int safe_smp_processor_id(void);
 extern int __cpu_disable(void);
 extern void __cpu_die(unsigned int cpu);
 extern void prefill_possible_map(void);
 extern unsigned num_processors;
 extern unsigned disabled_cpus;
 
-#endif /* !ASSEMBLY */
-
 #define NO_PROC_ID             0xFF            /* No processor magic marker */
 
 #endif
 
-#ifndef ASSEMBLY
 /*
  * Some lowlevel functions might want to know about
  * the real APIC ID <-> CPU # mapping.
@@ -109,11 +95,8 @@ static inline int cpu_present_to_apicid(int mps_cpu)
                return BAD_APICID;
 }
 
-#endif /* !ASSEMBLY */
-
 #ifndef CONFIG_SMP
 #define stack_smp_processor_id() 0
-#define safe_smp_processor_id() 0
 #define cpu_logical_map(x) (x)
 #else
 #include <asm/thread_info.h>
@@ -125,19 +108,23 @@ static inline int cpu_present_to_apicid(int mps_cpu)
 })
 #endif
 
-#ifndef __ASSEMBLY__
 static __inline int logical_smp_processor_id(void)
 {
        /* we don't want to mark this access volatile - bad code generation */
        return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
 }
-#endif
 
 #ifdef CONFIG_SMP
 #define cpu_physical_id(cpu)           x86_cpu_to_apicid[cpu]
 #else
 #define cpu_physical_id(cpu)           boot_cpu_id
-#endif
-
+static inline int smp_call_function_single(int cpuid, void (*func) (void *info),
+                               void *info, int retry, int wait)
+{
+       /* Disable interrupts here? */
+       func(info);
+       return 0;
+}
+#endif /* !CONFIG_SMP */
 #endif
 
index 248a79f0eaffcd306968be3e29980e95aece7940..3daf5b0059054994c04ba2bce41a8dfa81f701fc 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/atomic.h>
 #include <asm/rwlock.h>
 #include <asm/page.h>
+#include <asm/processor.h>
 
 /*
  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  * (the type definitions are in asm/spinlock_types.h)
  */
 
-#define __raw_spin_is_locked(x) \
-               (*(volatile signed int *)(&(x)->slock) <= 0)
-
-#define __raw_spin_lock_string \
-       "\n1:\t" \
-       LOCK_PREFIX " ; decl %0\n\t" \
-       "js 2f\n" \
-       LOCK_SECTION_START("") \
-       "2:\t" \
-       "rep;nop\n\t" \
-       "cmpl $0,%0\n\t" \
-       "jle 2b\n\t" \
-       "jmp 1b\n" \
-       LOCK_SECTION_END
-
-#define __raw_spin_lock_string_up \
-       "\n\tdecl %0"
-
-#define __raw_spin_unlock_string \
-       "movl $1,%0" \
-               :"=m" (lock->slock) : : "memory"
+static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
+{
+       return *(volatile signed int *)(&(lock)->slock) <= 0;
+}
 
 static inline void __raw_spin_lock(raw_spinlock_t *lock)
 {
-       asm volatile(__raw_spin_lock_string : "=m" (lock->slock) : : "memory");
+       asm volatile(
+               "\n1:\t"
+               LOCK_PREFIX " ; decl %0\n\t"
+               "jns 2f\n"
+               "3:\n"
+               "rep;nop\n\t"
+               "cmpl $0,%0\n\t"
+               "jle 3b\n\t"
+               "jmp 1b\n"
+               "2:\t" : "=m" (lock->slock) : : "memory");
 }
 
 #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
@@ -49,7 +42,7 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock)
 {
        int oldval;
 
-       __asm__ __volatile__(
+       asm volatile(
                "xchgl %0,%1"
                :"=q" (oldval), "=m" (lock->slock)
                :"0" (0) : "memory");
@@ -59,13 +52,14 @@ static inline int __raw_spin_trylock(raw_spinlock_t *lock)
 
 static inline void __raw_spin_unlock(raw_spinlock_t *lock)
 {
-       __asm__ __volatile__(
-               __raw_spin_unlock_string
-       );
+       asm volatile("movl $1,%0" :"=m" (lock->slock) :: "memory");
 }
 
-#define __raw_spin_unlock_wait(lock) \
-       do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
+static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
+{
+       while (__raw_spin_is_locked(lock))
+               cpu_relax();
+}
 
 /*
  * Read-write spinlocks, allowing multiple readers
@@ -79,26 +73,34 @@ static inline void __raw_spin_unlock(raw_spinlock_t *lock)
  *
  * On x86, we implement read-write locks as a 32-bit counter
  * with the high bit (sign) being the "contended" bit.
- *
- * The inline assembly is non-obvious. Think about it.
- *
- * Changed to use the same technique as rw semaphores.  See
- * semaphore.h for details.  -ben
- *
- * the helpers are in arch/i386/kernel/semaphore.c
  */
 
-#define __raw_read_can_lock(x)         ((int)(x)->lock > 0)
-#define __raw_write_can_lock(x)                ((x)->lock == RW_LOCK_BIAS)
+static inline int __raw_read_can_lock(raw_rwlock_t *lock)
+{
+       return (int)(lock)->lock > 0;
+}
+
+static inline int __raw_write_can_lock(raw_rwlock_t *lock)
+{
+       return (lock)->lock == RW_LOCK_BIAS;
+}
 
 static inline void __raw_read_lock(raw_rwlock_t *rw)
 {
-       __build_read_lock(rw, "__read_lock_failed");
+       asm volatile(LOCK_PREFIX "subl $1,(%0)\n\t"
+                    "jns 1f\n"
+                    "call __read_lock_failed\n"
+                    "1:\n"
+                    ::"D" (rw), "i" (RW_LOCK_BIAS) : "memory");
 }
 
 static inline void __raw_write_lock(raw_rwlock_t *rw)
 {
-       __build_write_lock(rw, "__write_lock_failed");
+       asm volatile(LOCK_PREFIX "subl %1,(%0)\n\t"
+                    "jz 1f\n"
+                    "\tcall __write_lock_failed\n\t"
+                    "1:\n"
+                    ::"D" (rw), "i" (RW_LOCK_BIAS) : "memory");
 }
 
 static inline int __raw_read_trylock(raw_rwlock_t *lock)
diff --git a/include/asm-x86_64/stacktrace.h b/include/asm-x86_64/stacktrace.h
new file mode 100644 (file)
index 0000000..5eb9799
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _ASM_STACKTRACE_H
+#define _ASM_STACKTRACE_H 1
+
+/* Generic stack tracer with callbacks */
+
+struct stacktrace_ops {
+       void (*warning)(void *data, char *msg);
+       /* msg must contain %s for the symbol */
+       void (*warning_symbol)(void *data, char *msg, unsigned long symbol);
+       void (*address)(void *data, unsigned long address);
+       /* On negative return stop dumping */
+       int (*stack)(void *data, char *name);
+};
+
+void dump_trace(struct task_struct *tsk, struct pt_regs *regs, unsigned long *stack,
+               struct stacktrace_ops *ops, void *data);
+
+#endif
index 6bf170bceae1b4a7d114305c340240670698a032..bd376bc8c4ab26b5702bf667ad84f18f38fb5184 100644 (file)
 #define __RESTORE(reg,offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
 
 /* frame pointer must be last for get_wchan */
-#define SAVE_CONTEXT    "pushq %%rbp ; movq %%rsi,%%rbp\n\t"
-#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp\n\t"
+#define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
+#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
 
 #define __EXTRA_CLOBBER  \
        ,"rcx","rbx","rdx","r8","r9","r10","r11","r12","r13","r14","r15"
 
+/* Save restore flags to clear handle leaking NT */
 #define switch_to(prev,next,last) \
        asm volatile(SAVE_CONTEXT                                                   \
                     "movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */       \
index 53e9a68b33360bcf372d04b4586231d9b94311b1..dbb047febc5e5ad7ad2a0384d67540f47c9618ee 100644 (file)
@@ -24,7 +24,6 @@
 #ifndef _ASM_X86_64_TCE_H
 #define _ASM_X86_64_TCE_H
 
-extern void* tce_table_kva[];
 extern unsigned int specified_table_size;
 struct iommu_table;
 
diff --git a/include/asm-x86_64/therm_throt.h b/include/asm-x86_64/therm_throt.h
new file mode 100644 (file)
index 0000000..5aac059
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-i386/therm_throt.h>
index 2029b00351f3f6a1eb2e828bbb2a931d7910a1dd..787a08114b4847c0e4d37de1157515355cc4adce 100644 (file)
@@ -114,11 +114,14 @@ static inline struct thread_info *stack_thread_info(void)
 #define TIF_IRET               5       /* force IRET */
 #define TIF_SYSCALL_AUDIT      7       /* syscall auditing active */
 #define TIF_SECCOMP            8       /* secure computing */
+#define TIF_RESTORE_SIGMASK    9       /* restore signal mask in do_signal */
 /* 16 free */
 #define TIF_IA32               17      /* 32bit process */ 
 #define TIF_FORK               18      /* ret_from_fork */
 #define TIF_ABI_PENDING                19
 #define TIF_MEMDIE             20
+#define TIF_DEBUG              21      /* uses debug registers */
+#define TIF_IO_BITMAP          22      /* uses I/O bitmap */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
@@ -128,9 +131,12 @@ static inline struct thread_info *stack_thread_info(void)
 #define _TIF_IRET              (1<<TIF_IRET)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
+#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_IA32              (1<<TIF_IA32)
 #define _TIF_FORK              (1<<TIF_FORK)
 #define _TIF_ABI_PENDING       (1<<TIF_ABI_PENDING)
+#define _TIF_DEBUG             (1<<TIF_DEBUG)
+#define _TIF_IO_BITMAP         (1<<TIF_IO_BITMAP)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
@@ -138,6 +144,9 @@ static inline struct thread_info *stack_thread_info(void)
 /* work to do on any return to user space */
 #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
 
+/* flags to check in __switch_to() */
+#define _TIF_WORK_CTXSW (_TIF_DEBUG|_TIF_IO_BITMAP)
+
 #define PREEMPT_ACTIVE     0x10000000
 
 /*
index d16d5b60f419b4680d20bd14bb7b93bba8f74308..983bd296c81a304281530c972f6f38c4b1384d95 100644 (file)
@@ -4,44 +4,44 @@
 #include <linux/mm.h>
 #include <asm/processor.h>
 
-#define __flush_tlb()                                                  \
-       do {                                                            \
-               unsigned long tmpreg;                                   \
-                                                                       \
-               __asm__ __volatile__(                                   \
-                       "movq %%cr3, %0;  # flush TLB \n"               \
-                       "movq %0, %%cr3;              \n"               \
-                       : "=r" (tmpreg)                                 \
-                       :: "memory");                                   \
-       } while (0)
+static inline unsigned long get_cr3(void)
+{
+       unsigned long cr3;
+       asm volatile("mov %%cr3,%0" : "=r" (cr3));
+       return cr3;
+}
 
-/*
- * Global pages have to be flushed a bit differently. Not a real
- * performance problem because this does not happen often.
- */
-#define __flush_tlb_global()                                           \
-       do {                                                            \
-               unsigned long tmpreg, cr4, cr4_orig;                    \
-                                                                       \
-               __asm__ __volatile__(                                   \
-                       "movq %%cr4, %2;  # turn off PGE     \n"        \
-                       "movq %2, %1;                        \n"        \
-                       "andq %3, %1;                        \n"        \
-                       "movq %1, %%cr4;                     \n"        \
-                       "movq %%cr3, %0;  # flush TLB        \n"        \
-                       "movq %0, %%cr3;                     \n"        \
-                       "movq %2, %%cr4;  # turn PGE back on \n"        \
-                       : "=&r" (tmpreg), "=&r" (cr4), "=&r" (cr4_orig) \
-                       : "i" (~X86_CR4_PGE)                            \
-                       : "memory");                                    \
-       } while (0)
-
-extern unsigned long pgkern_mask;
-
-#define __flush_tlb_all() __flush_tlb_global()
+static inline void set_cr3(unsigned long cr3)
+{
+       asm volatile("mov %0,%%cr3" :: "r" (cr3) : "memory");
+}
+
+static inline void __flush_tlb(void)
+{
+       set_cr3(get_cr3());
+}
+
+static inline unsigned long get_cr4(void)
+{
+       unsigned long cr4;
+       asm volatile("mov %%cr4,%0" : "=r" (cr4));
+       return cr4;
+}
+
+static inline void set_cr4(unsigned long cr4)
+{
+       asm volatile("mov %0,%%cr4" :: "r" (cr4) : "memory");
+}
+
+static inline void __flush_tlb_all(void)
+{
+       unsigned long cr4 = get_cr4();
+       set_cr4(cr4 & ~X86_CR4_PGE);    /* clear PGE */
+       set_cr4(cr4);                   /* write old PGE again and flush TLBs */
+}
 
 #define __flush_tlb_one(addr) \
-       __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
+       __asm__ __volatile__("invlpg (%0)" :: "r" (addr) : "memory")
 
 
 /*
index 1e1fa003daa3364ca9a2e96c0c1e7af75216cbd5..e856570c068952045b73bd25a2cf45d22ed7aeb2 100644 (file)
@@ -84,7 +84,7 @@ struct exception_table_entry
  */
 
 #define __get_user_x(size,ret,x,ptr) \
-       __asm__ __volatile__("call __get_user_" #size \
+       asm volatile("call __get_user_" #size \
                :"=a" (ret),"=d" (x) \
                :"c" (ptr) \
                :"r8")
@@ -101,7 +101,7 @@ struct exception_table_entry
        case 8:  __get_user_x(8,__ret_gu,__val_gu,ptr); break;          \
        default: __get_user_bad(); break;                               \
        }                                                               \
-       (x) = (__typeof__(*(ptr)))__val_gu;                             \
+       (x) = (typeof(*(ptr)))__val_gu;                         \
        __ret_gu;                                                       \
 })
 
@@ -112,7 +112,7 @@ extern void __put_user_8(void);
 extern void __put_user_bad(void);
 
 #define __put_user_x(size,ret,x,ptr)                                   \
-       __asm__ __volatile__("call __put_user_" #size                   \
+       asm volatile("call __put_user_" #size                   \
                :"=a" (ret)                                             \
                :"c" (ptr),"d" (x)                                      \
                :"r8")
@@ -139,7 +139,7 @@ extern void __put_user_bad(void);
 #define __put_user_check(x,ptr,size)                   \
 ({                                                     \
        int __pu_err;                                   \
-       __typeof__(*(ptr)) __user *__pu_addr = (ptr);   \
+       typeof(*(ptr)) __user *__pu_addr = (ptr);       \
        switch (size) {                                 \
        case 1: __put_user_x(1,__pu_err,x,__pu_addr); break;    \
        case 2: __put_user_x(2,__pu_err,x,__pu_addr); break;    \
@@ -173,7 +173,7 @@ struct __large_struct { unsigned long buf[100]; };
  * aliasing issues.
  */
 #define __put_user_asm(x, addr, err, itype, rtype, ltype, errno)       \
-       __asm__ __volatile__(                                   \
+       asm volatile(                                   \
                "1:     mov"itype" %"rtype"1,%2\n"              \
                "2:\n"                                          \
                ".section .fixup,\"ax\"\n"                      \
@@ -193,7 +193,7 @@ struct __large_struct { unsigned long buf[100]; };
        int __gu_err;                                           \
        unsigned long __gu_val;                                 \
        __get_user_size(__gu_val,(ptr),(size),__gu_err);        \
-       (x) = (__typeof__(*(ptr)))__gu_val;                     \
+       (x) = (typeof(*(ptr)))__gu_val;                 \
        __gu_err;                                               \
 })
 
@@ -217,7 +217,7 @@ do {                                                                        \
 } while (0)
 
 #define __get_user_asm(x, addr, err, itype, rtype, ltype, errno)       \
-       __asm__ __volatile__(                                   \
+       asm volatile(                                   \
                "1:     mov"itype" %2,%"rtype"1\n"              \
                "2:\n"                                          \
                ".section .fixup,\"ax\"\n"                      \
@@ -237,15 +237,20 @@ do {                                                                      \
  */
 
 /* Handles exceptions in both to and from, but doesn't do access_ok */
-extern unsigned long copy_user_generic(void *to, const void *from, unsigned len); 
-
-extern unsigned long copy_to_user(void __user *to, const void *from, unsigned len); 
-extern unsigned long copy_from_user(void *to, const void __user *from, unsigned len); 
-extern unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len); 
-
-static __always_inline int __copy_from_user(void *dst, const void __user *src, unsigned size)
+__must_check unsigned long
+copy_user_generic(void *to, const void *from, unsigned len);
+
+__must_check unsigned long
+copy_to_user(void __user *to, const void *from, unsigned len);
+__must_check unsigned long
+copy_from_user(void *to, const void __user *from, unsigned len);
+__must_check unsigned long
+copy_in_user(void __user *to, const void __user *from, unsigned len);
+
+static __always_inline __must_check
+int __copy_from_user(void *dst, const void __user *src, unsigned size)
 { 
-       int ret = 0;
+       int ret = 0;
        if (!__builtin_constant_p(size))
                return copy_user_generic(dst,(__force void *)src,size);
        switch (size) { 
@@ -272,9 +277,10 @@ static __always_inline int __copy_from_user(void *dst, const void __user *src, u
        }
 }      
 
-static __always_inline int __copy_to_user(void __user *dst, const void *src, unsigned size)
+static __always_inline __must_check
+int __copy_to_user(void __user *dst, const void *src, unsigned size)
 { 
-       int ret = 0;
+       int ret = 0;
        if (!__builtin_constant_p(size))
                return copy_user_generic((__force void *)dst,src,size);
        switch (size) { 
@@ -303,10 +309,10 @@ static __always_inline int __copy_to_user(void __user *dst, const void *src, uns
        }
 }      
 
-
-static __always_inline int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
+static __always_inline __must_check
+int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
 { 
-       int ret = 0;
+       int ret = 0;
        if (!__builtin_constant_p(size))
                return copy_user_generic((__force void *)dst,(__force void *)src,size);
        switch (size) { 
@@ -344,15 +350,17 @@ static __always_inline int __copy_in_user(void __user *dst, const void __user *s
        }
 }      
 
-long strncpy_from_user(char *dst, const char __user *src, long count);
-long __strncpy_from_user(char *dst, const char __user *src, long count);
-long strnlen_user(const char __user *str, long n);
-long __strnlen_user(const char __user *str, long n);
-long strlen_user(const char __user *str);
-unsigned long clear_user(void __user *mem, unsigned long len);
-unsigned long __clear_user(void __user *mem, unsigned long len);
-
-#define __copy_to_user_inatomic __copy_to_user
-#define __copy_from_user_inatomic __copy_from_user
+__must_check long 
+strncpy_from_user(char *dst, const char __user *src, long count);
+__must_check long 
+__strncpy_from_user(char *dst, const char __user *src, long count);
+__must_check long strnlen_user(const char __user *str, long n);
+__must_check long __strnlen_user(const char __user *str, long n);
+__must_check long strlen_user(const char __user *str);
+__must_check unsigned long clear_user(void __user *mem, unsigned long len);
+__must_check unsigned long __clear_user(void __user *mem, unsigned long len);
+
+__must_check long __copy_from_user_inatomic(void *dst, const void __user *src, unsigned size);
+#define __copy_to_user_inatomic copy_user_generic
 
 #endif /* __X86_64_UACCESS_H */
index 80fd48e84bbb6ddbe809c7a169d49d8ab55c5685..6137146516d3905ef58c931f56fc7951a26ad194 100644 (file)
@@ -600,9 +600,9 @@ __SYSCALL(__NR_fchmodat, sys_fchmodat)
 #define __NR_faccessat         269
 __SYSCALL(__NR_faccessat, sys_faccessat)
 #define __NR_pselect6          270
-__SYSCALL(__NR_pselect6, sys_ni_syscall)       /* for now */
+__SYSCALL(__NR_pselect6, sys_pselect6)
 #define __NR_ppoll             271
-__SYSCALL(__NR_ppoll,  sys_ni_syscall)         /* for now */
+__SYSCALL(__NR_ppoll,  sys_ppoll)
 #define __NR_unshare           272
 __SYSCALL(__NR_unshare,        sys_unshare)
 #define __NR_set_robust_list   273
@@ -623,16 +623,17 @@ __SYSCALL(__NR_move_pages, sys_move_pages)
 #ifdef __KERNEL__
 
 #define __NR_syscall_max __NR_move_pages
+#include <linux/err.h>
 
 #ifndef __NO_STUBS
 
-/* user-visible error numbers are in the range -1 - -4095 */
+/* user-visible error numbers are in the range -1 - -MAX_ERRNO */
 
 #define __syscall_clobber "r11","rcx","memory" 
 
 #define __syscall_return(type, res) \
 do { \
-       if ((unsigned long)(res) >= (unsigned long)(-127)) { \
+       if ((unsigned long)(res) >= (unsigned long)(-MAX_ERRNO)) { \
                errno = -(res); \
                res = -1; \
        } \
@@ -658,6 +659,7 @@ do { \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_TIME
 #define __ARCH_WANT_COMPAT_SYS_TIME
 
index 1f6e9bfb569e7ef6f645af572ee2a030c21f1a83..2e7ff10fd7751db2e967101c4b7749ad32b7f3a8 100644 (file)
@@ -18,6 +18,7 @@ struct unwind_frame_info
 {
        struct pt_regs regs;
        struct task_struct *task;
+       unsigned call_frame:1;
 };
 
 #define UNW_PC(frame)        (frame)->regs.rip
@@ -57,6 +58,10 @@ struct unwind_frame_info
        PTREGS_INFO(r15), \
        PTREGS_INFO(rip)
 
+#define UNW_DEFAULT_RA(raItem, dataAlign) \
+       ((raItem).where == Memory && \
+        !((raItem).value * (dataAlign) + 8))
+
 static inline void arch_unw_init_frame_info(struct unwind_frame_info *info,
                                             /*const*/ struct pt_regs *regs)
 {
@@ -94,8 +99,8 @@ static inline int arch_unw_user_mode(const struct unwind_frame_info *info)
 
 #else
 
-#define UNW_PC(frame) ((void)(frame), 0)
-#define UNW_SP(frame) ((void)(frame), 0)
+#define UNW_PC(frame) ((void)(frame), 0UL)
+#define UNW_SP(frame) ((void)(frame), 0UL)
 
 static inline int arch_unw_user_mode(const void *info)
 {
index 146b24402a5f915d07c748956dd48adcc8e2f8d9..2281e9399b9677ddf64211164f06d221604c542a 100644 (file)
@@ -4,6 +4,7 @@
 enum vsyscall_num {
        __NR_vgettimeofday,
        __NR_vtime,
+       __NR_vgetcpu,
 };
 
 #define VSYSCALL_START (-10UL << 20)
@@ -15,6 +16,7 @@ enum vsyscall_num {
 #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_wall_jiffies __attribute__ ((unused, __section__ (".wall_jiffies"), aligned(16)))
 #define __section_jiffies __attribute__ ((unused, __section__ (".jiffies"), aligned(16)))
 #define __section_sys_tz __attribute__ ((unused, __section__ (".sys_tz"), aligned(16)))
@@ -26,6 +28,9 @@ enum vsyscall_num {
 #define VXTIME_HPET    2
 #define VXTIME_PMTMR   3
 
+#define VGETCPU_RDTSCP 1
+#define VGETCPU_LSL    2
+
 struct vxtime_data {
        long hpet_address;      /* HPET base address */
        int last;
@@ -40,6 +45,7 @@ struct vxtime_data {
 
 /* vsyscall space (readonly) */
 extern struct vxtime_data __vxtime;
+extern int __vgetcpu_mode;
 extern struct timespec __xtime;
 extern volatile unsigned long __jiffies;
 extern unsigned long __wall_jiffies;
@@ -48,6 +54,7 @@ extern seqlock_t __xtime_lock;
 
 /* kernel space (writeable) */
 extern struct vxtime_data vxtime;
+extern int vgetcpu_mode;
 extern unsigned long wall_jiffies;
 extern struct timezone sys_tz;
 extern int sysctl_vsyscall;
@@ -55,6 +62,8 @@ extern seqlock_t xtime_lock;
 
 extern int sysctl_vsyscall;
 
+extern void vsyscall_set_cpu(int cpu);
+
 #define ARCH_HAVE_XTIME_LOCK 1
 
 #endif /* __KERNEL__ */
diff --git a/include/linux/aer.h b/include/linux/aer.h
new file mode 100644 (file)
index 0000000..402e178
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2006 Intel Corp.
+ *     Tom Long Nguyen (tom.l.nguyen@intel.com)
+ *     Zhang Yanmin (yanmin.zhang@intel.com)
+ */
+
+#ifndef _AER_H_
+#define _AER_H_
+
+#if defined(CONFIG_PCIEAER)
+/* pci-e port driver needs this function to enable aer */
+extern int pci_enable_pcie_error_reporting(struct pci_dev *dev);
+extern int pci_find_aer_capability(struct pci_dev *dev);
+extern int pci_disable_pcie_error_reporting(struct pci_dev *dev);
+extern int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev);
+#else
+#define pci_enable_pcie_error_reporting(dev)           do { } while (0)
+#define pci_find_aer_capability(dev)                   do { } while (0)
+#define pci_disable_pcie_error_reporting(dev)          do { } while (0)
+#define pci_cleanup_aer_uncorrect_error_status(dev)    do { } while (0)
+#endif
+
+#endif //_AER_H_
+
index 2216638962d2790fa8d5e4776d17559c3717a69a..ee5f53f2ca15a171c74cf3ec392b2b407dc22b8c 100644 (file)
@@ -23,5 +23,7 @@ void cdev_del(struct cdev *);
 
 void cd_forget(struct inode *);
 
+extern struct backing_dev_info directly_mappable_cdev_bdi;
+
 #endif
 #endif
index 9b4f110949375c78b8fa1db830009e64ab3fbf73..060b96112ec66fcfebcd6e8f5ea4c86f4bec5dde 100644 (file)
@@ -99,6 +99,11 @@ extern void __chk_io_ptr(void __iomem *);
 #define __must_check
 #endif
 
+#ifndef CONFIG_ENABLE_MUST_CHECK
+#undef __must_check
+#define __must_check
+#endif
+
 /*
  * Allow us to avoid 'defined but not used' warnings on functions and data,
  * as well as force them to be emitted to the assembly file.
index 1e5f30da98bc528b9ab9aaf629a673cb50e6f8ae..662e6a10144e5b453b2ad11b02fc7314bd33816e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kobject.h>
 #include <linux/klist.h>
 #include <linux/list.h>
+#include <linux/compiler.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/pm.h>
@@ -51,14 +52,17 @@ struct bus_type {
        int             (*probe)(struct device * dev);
        int             (*remove)(struct device * dev);
        void            (*shutdown)(struct device * dev);
-       int             (*suspend)(struct device * dev, pm_message_t state);
-       int             (*resume)(struct device * dev);
+
+       int (*suspend)(struct device * dev, pm_message_t state);
+       int (*suspend_late)(struct device * dev, pm_message_t state);
+       int (*resume_early)(struct device * dev);
+       int (*resume)(struct device * dev);
 };
 
-extern int bus_register(struct bus_type * bus);
+extern int __must_check bus_register(struct bus_type * bus);
 extern void bus_unregister(struct bus_type * bus);
 
-extern void bus_rescan_devices(struct bus_type * bus);
+extern int __must_check bus_rescan_devices(struct bus_type * bus);
 
 /* iterator helpers for buses */
 
@@ -67,9 +71,9 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,
 struct device * bus_find_device(struct bus_type *bus, struct device *start,
                                void *data, int (*match)(struct device *, void *));
 
-int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, 
-                    void * data, int (*fn)(struct device_driver *, void *));
-
+int __must_check bus_for_each_drv(struct bus_type *bus,
+               struct device_driver *start, void *data,
+               int (*fn)(struct device_driver *, void *));
 
 /* driverfs interface for exporting bus attributes */
 
@@ -82,7 +86,8 @@ struct bus_attribute {
 #define BUS_ATTR(_name,_mode,_show,_store)     \
 struct bus_attribute bus_attr_##_name = __ATTR(_name,_mode,_show,_store)
 
-extern int bus_create_file(struct bus_type *, struct bus_attribute *);
+extern int __must_check bus_create_file(struct bus_type *,
+                                       struct bus_attribute *);
 extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
 
 struct device_driver {
@@ -101,16 +106,18 @@ struct device_driver {
        void    (*shutdown)     (struct device * dev);
        int     (*suspend)      (struct device * dev, pm_message_t state);
        int     (*resume)       (struct device * dev);
+
+       unsigned int multithread_probe:1;
 };
 
 
-extern int driver_register(struct device_driver * drv);
+extern int __must_check driver_register(struct device_driver * drv);
 extern void driver_unregister(struct device_driver * drv);
 
 extern struct device_driver * get_driver(struct device_driver * drv);
 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 */
 
@@ -123,16 +130,17 @@ struct driver_attribute {
 #define DRIVER_ATTR(_name,_mode,_show,_store)  \
 struct driver_attribute driver_attr_##_name = __ATTR(_name,_mode,_show,_store)
 
-extern int driver_create_file(struct device_driver *, struct driver_attribute *);
+extern int __must_check driver_create_file(struct device_driver *,
+                                       struct driver_attribute *);
 extern void driver_remove_file(struct device_driver *, struct driver_attribute *);
 
-extern int driver_for_each_device(struct device_driver * drv, struct device * start,
-                                 void * data, int (*fn)(struct device *, void *));
+extern int __must_check driver_for_each_device(struct device_driver * drv,
+               struct device *start, void *data,
+               int (*fn)(struct device *, void *));
 struct device * driver_find_device(struct device_driver *drv,
                                   struct device *start, void *data,
                                   int (*match)(struct device *, void *));
 
-
 /*
  * device classes
  */
@@ -146,17 +154,26 @@ struct class {
        struct list_head        interfaces;
        struct semaphore        sem;    /* locks both the children and interfaces lists */
 
+       struct kobject          *virtual_dir;
+
        struct class_attribute          * class_attrs;
        struct class_device_attribute   * class_dev_attrs;
+       struct device_attribute         * dev_attrs;
 
        int     (*uevent)(struct class_device *dev, char **envp,
                           int num_envp, char *buffer, int buffer_size);
+       int     (*dev_uevent)(struct device *dev, char **envp, int num_envp,
+                               char *buffer, int buffer_size);
 
        void    (*release)(struct class_device *dev);
        void    (*class_release)(struct class *class);
+       void    (*dev_release)(struct device *dev);
+
+       int     (*suspend)(struct device *, pm_message_t state);
+       int     (*resume)(struct device *);
 };
 
-extern int class_register(struct class *);
+extern int __must_check class_register(struct class *);
 extern void class_unregister(struct class *);
 
 
@@ -169,7 +186,8 @@ struct class_attribute {
 #define CLASS_ATTR(_name,_mode,_show,_store)                   \
 struct class_attribute class_attr_##_name = __ATTR(_name,_mode,_show,_store) 
 
-extern int class_create_file(struct class *, const struct class_attribute *);
+extern int __must_check class_create_file(struct class *,
+                                       const struct class_attribute *);
 extern void class_remove_file(struct class *, const struct class_attribute *);
 
 struct class_device_attribute {
@@ -182,7 +200,7 @@ struct class_device_attribute {
 struct class_device_attribute class_device_attr_##_name =      \
        __ATTR(_name,_mode,_show,_store)
 
-extern int class_device_create_file(struct class_device *,
+extern int __must_check class_device_create_file(struct class_device *,
                                    const struct class_device_attribute *);
 
 /**
@@ -242,10 +260,10 @@ class_set_devdata (struct class_device *dev, void *data)
 }
 
 
-extern int class_device_register(struct class_device *);
+extern int __must_check class_device_register(struct class_device *);
 extern void class_device_unregister(struct class_device *);
 extern void class_device_initialize(struct class_device *);
-extern int class_device_add(struct class_device *);
+extern int __must_check class_device_add(struct class_device *);
 extern void class_device_del(struct class_device *);
 
 extern int class_device_rename(struct class_device *, char *);
@@ -255,7 +273,7 @@ extern void class_device_put(struct class_device *);
 
 extern void class_device_remove_file(struct class_device *, 
                                     const struct class_device_attribute *);
-extern int class_device_create_bin_file(struct class_device *,
+extern int __must_check class_device_create_bin_file(struct class_device *,
                                        struct bin_attribute *);
 extern void class_device_remove_bin_file(struct class_device *,
                                         struct bin_attribute *);
@@ -266,22 +284,23 @@ struct class_interface {
 
        int (*add)      (struct class_device *, struct class_interface *);
        void (*remove)  (struct class_device *, struct class_interface *);
+       int (*add_dev)          (struct device *, struct class_interface *);
+       void (*remove_dev)      (struct device *, struct class_interface *);
 };
 
-extern int class_interface_register(struct class_interface *);
+extern int __must_check class_interface_register(struct class_interface *);
 extern void class_interface_unregister(struct class_interface *);
 
-extern struct class *class_create(struct module *owner, char *name);
+extern struct class *class_create(struct module *owner, const char *name);
 extern void class_destroy(struct class *cls);
 extern struct class_device *class_device_create(struct class *cls,
                                                struct class_device *parent,
                                                dev_t devt,
                                                struct device *device,
-                                               char *fmt, ...)
+                                               const char *fmt, ...)
                                        __attribute__((format(printf,5,6)));
 extern void class_device_destroy(struct class *cls, dev_t devt);
 
-
 /* interface for exporting device attributes */
 struct device_attribute {
        struct attribute        attr;
@@ -294,8 +313,13 @@ struct device_attribute {
 #define DEVICE_ATTR(_name,_mode,_show,_store) \
 struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store)
 
-extern int device_create_file(struct device *device, struct device_attribute * entry);
+extern int __must_check device_create_file(struct device *device,
+                                       struct device_attribute * entry);
 extern void device_remove_file(struct device * dev, struct device_attribute * attr);
+extern int __must_check device_create_bin_file(struct device *dev,
+                                              struct bin_attribute *attr);
+extern void device_remove_bin_file(struct device *dev,
+                                  struct bin_attribute *attr);
 struct device {
        struct klist            klist_children;
        struct klist_node       knode_parent;           /* node in sibling list */
@@ -305,6 +329,7 @@ struct device {
 
        struct kobject kobj;
        char    bus_id[BUS_ID_SIZE];    /* position on parent bus */
+       unsigned                is_registered:1;
        struct device_attribute uevent_attr;
        struct device_attribute *devt_attr;
 
@@ -338,6 +363,7 @@ struct device {
        struct list_head        node;
        struct class            *class;         /* optional*/
        dev_t                   devt;           /* dev_t, creates the sysfs "dev" */
+       struct attribute_group  **groups;       /* optional groups */
 
        void    (*release)(struct device * dev);
 };
@@ -356,38 +382,41 @@ dev_set_drvdata (struct device *dev, void *data)
 
 static inline int device_is_registered(struct device *dev)
 {
-       return klist_node_attached(&dev->knode_bus);
+       return dev->is_registered;
 }
 
 /*
  * High level routines for use by the bus drivers
  */
-extern int device_register(struct device * dev);
+extern int __must_check device_register(struct device * dev);
 extern void device_unregister(struct device * dev);
 extern void device_initialize(struct device * dev);
-extern int device_add(struct device * dev);
+extern int __must_check device_add(struct device * dev);
 extern void device_del(struct device * dev);
-extern int device_for_each_child(struct device *, void *,
+extern int __must_check device_for_each_child(struct device *, void *,
                     int (*fn)(struct device *, void *));
+extern int device_rename(struct device *dev, char *new_name);
 
 /*
  * Manual binding of a device to driver. See drivers/base/bus.c
  * for information on use.
  */
-extern void device_bind_driver(struct device * dev);
+extern int __must_check device_bind_driver(struct device *dev);
 extern void device_release_driver(struct device * dev);
-extern int  device_attach(struct device * dev);
-extern void driver_attach(struct device_driver * drv);
-extern void device_reprobe(struct device *dev);
+extern int  __must_check device_attach(struct device * dev);
+extern int __must_check driver_attach(struct device_driver *drv);
+extern int __must_check device_reprobe(struct device *dev);
 
 /*
  * Easy functions for dynamically creating devices on the fly
  */
 extern struct device *device_create(struct class *cls, struct device *parent,
-                                   dev_t devt, char *fmt, ...)
+                                   dev_t devt, const char *fmt, ...)
                                    __attribute__((format(printf,4,5)));
 extern void device_destroy(struct class *cls, dev_t devt);
 
+extern int virtual_device_parent(struct device *dev);
+
 /*
  * Platform "fixup" functions - allow the platform to have their say
  * about devices and actions that the general device layer doesn't
@@ -412,7 +441,7 @@ extern void device_shutdown(void);
 
 
 /* drivers/base/firmware.c */
-extern int firmware_register(struct subsystem *);
+extern int __must_check firmware_register(struct subsystem *);
 extern void firmware_unregister(struct subsystem *);
 
 /* debugging and troubleshooting/diagnostic helpers. */
index 162512b886f7e59d8fd038d3cf7bd478f2139f79..b2b3e68aa5128b1076233547627df096e5200ed2 100644 (file)
@@ -52,6 +52,7 @@
 #define EDD_CL_EQUALS   0x3d646465     /* "edd=" */
 #define EDD_CL_OFF      0x666f         /* "of" for off  */
 #define EDD_CL_SKIP     0x6b73         /* "sk" for skipmbr */
+#define EDD_CL_ON       0x6e6f        /* "on" for on */
 
 #ifndef __ASSEMBLY__
 
index 4079242dced874a79caf77bb86313a5e1a658bd6..1ff7c1392525884b0f7ee005ae21ff822b01ae56 100644 (file)
@@ -3,8 +3,8 @@
 
 #include <linux/ioport.h>
 #include <linux/device.h>
+#include <linux/mod_devicetable.h>
 
-#define EISA_SIG_LEN   8
 #define EISA_MAX_SLOTS 8
 
 #define EISA_MAX_RESOURCES 4
 #define EISA_CONFIG_ENABLED         1
 #define EISA_CONFIG_FORCED          2
 
-/* The EISA signature, in ASCII form, null terminated */
-struct eisa_device_id {
-       char          sig[EISA_SIG_LEN];
-       unsigned long driver_data;
-};
-
 /* There is not much we can say about an EISA device, apart from
  * signature, slot number, and base address. dma_mask is set by
  * default to parent device mask..*/
index cd3b367f7445e5aa0f25ddbf2f0b96c44a19b94f..1ab1d44f8d3be7a28c8a1a849c72e1f841424015 100644 (file)
@@ -15,6 +15,8 @@
  */
 #define MAX_ERRNO      4095
 
+#ifndef __ASSEMBLY__
+
 #define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO)
 
 static inline void *ERR_PTR(long error)
@@ -32,4 +34,6 @@ static inline long IS_ERR(const void *ptr)
        return IS_ERR_VALUE((unsigned long)ptr);
 }
 
+#endif
+
 #endif /* _LINUX_ERR_H */
index 0eed918b38168a05a3847a641243a3622862aa10..cc08f56750da7cf7ed68c1349db063fd01a6be68 100644 (file)
@@ -460,7 +460,7 @@ struct ext3_super_block {
         */
        __u8    s_prealloc_blocks;      /* Nr of blocks to try to preallocate*/
        __u8    s_prealloc_dir_blocks;  /* Nr to preallocate for dirs */
-       __u16   s_reserved_gdt_blocks;  /* Per group desc for online growth */
+       __le16  s_reserved_gdt_blocks;  /* Per group desc for online growth */
        /*
         * Journaling support valid if EXT3_FEATURE_COMPAT_HAS_JOURNAL set.
         */
@@ -473,7 +473,7 @@ struct ext3_super_block {
        __u8    s_reserved_char_pad;
        __u16   s_reserved_word_pad;
        __le32  s_default_mount_opts;
-       __le32  s_first_meta_bg;        /* First metablock block group */
+       __le32  s_first_meta_bg;        /* First metablock block group */
        __u32   s_reserved[190];        /* Padding to the end of the block */
 };
 
index 2f18b9511f211f728bf1e631a554b53d1dd124ee..4395e5206746b33be79bd57bef264da8a74bcd0a 100644 (file)
@@ -35,7 +35,7 @@ struct ext3_reserve_window {
 };
 
 struct ext3_reserve_window_node {
-       struct rb_node          rsv_node;
+       struct rb_node          rsv_node;
        __u32                   rsv_goal_size;
        __u32                   rsv_alloc_hit;
        struct ext3_reserve_window      rsv_window;
index c8307c02dd07103c19bfd2dd38ece06470d12278..ce0e6109aff0cdb83e05cd350909da82b5a50d99 100644 (file)
@@ -23,7 +23,7 @@
 
 /* Define the number of blocks we need to account to a transaction to
  * modify one block of data.
- * 
+ *
  * We may have to touch one inode, one bitmap buffer, up to three
  * indirection blocks, the group and superblock summaries, and the data
  * block to complete the transaction.  */
 #endif
 
 int
-ext3_mark_iloc_dirty(handle_t *handle, 
+ext3_mark_iloc_dirty(handle_t *handle,
                     struct inode *inode,
                     struct ext3_iloc *iloc);
 
-/* 
+/*
  * On success, We end up with an outstanding reference count against
- * iloc->bh.  This _must_ be cleaned up later. 
+ * iloc->bh.  This _must_ be cleaned up later.
  */
 
-int ext3_reserve_inode_write(handle_t *handle, struct inode *inode, 
+int ext3_reserve_inode_write(handle_t *handle, struct inode *inode,
                        struct ext3_iloc *iloc);
 
 int ext3_mark_inode_dirty(handle_t *handle, struct inode *inode);
index 1d3e601ece7396263ef5cc40c14c6c0691548452..8f74dfbb2edd256c312b5db9efdc33e4cbeb3cbd 100644 (file)
@@ -512,7 +512,6 @@ struct inode {
        struct timespec         i_mtime;
        struct timespec         i_ctime;
        unsigned int            i_blkbits;
-       unsigned long           i_blksize;
        unsigned long           i_version;
        blkcnt_t                i_blocks;
        unsigned short          i_bytes;
@@ -528,11 +527,12 @@ struct inode {
 #ifdef CONFIG_QUOTA
        struct dquot            *i_dquot[MAXQUOTAS];
 #endif
-       /* These three should probably be a union */
        struct list_head        i_devices;
-       struct pipe_inode_info  *i_pipe;
-       struct block_device     *i_bdev;
-       struct cdev             *i_cdev;
+       union {
+               struct pipe_inode_info  *i_pipe;
+               struct block_device     *i_bdev;
+               struct cdev             *i_cdev;
+       };
        int                     i_cindex;
 
        __u32                   i_generation;
@@ -554,9 +554,7 @@ struct inode {
 
        atomic_t                i_writecount;
        void                    *i_security;
-       union {
-               void            *generic_ip;
-       } u;
+       void                    *i_private; /* fs or device private pointer */
 #ifdef __NEED_I_SIZE_ORDERED
        seqcount_t              i_size_seqcount;
 #endif
diff --git a/include/linux/getcpu.h b/include/linux/getcpu.h
new file mode 100644 (file)
index 0000000..031ed37
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _LINUX_GETCPU_H
+#define _LINUX_GETCPU_H 1
+
+/* Cache for getcpu() to speed it up. Results might be upto a jiffie
+   out of date, but will be faster.
+   User programs should not refer to the contents of this structure.
+   It is only a cache for vgetcpu(). It might change in future kernels.
+   The user program must store this information per thread (__thread)
+   If you want 100% accurate information pass NULL instead. */
+struct getcpu_cache {
+       unsigned long t0;
+       unsigned long t1;
+       unsigned long res[4];
+};
+
+#endif
index 8b34aabfe4c61129c78e378365372ae6831bc6c8..bf2b6bc3f6fd4fc35dec4dc8072b26c160458dfe 100644 (file)
@@ -67,7 +67,12 @@ struct vm_area_struct;
 #define GFP_HIGHUSER   (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | \
                         __GFP_HIGHMEM)
 
+#ifdef CONFIG_NUMA
 #define GFP_THISNODE   (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
+#else
+#define GFP_THISNODE   0
+#endif
+
 
 /* Flag - indicates that the buffer will be suitable for DMA.  Ignored on some
    platforms, used as appropriate on others */
index d5ebbb29aeaebc339fe893456bc2dba507f80453..d4b333938f73277790ae2a512b374da747512fae 100644 (file)
 #ifndef __HDLC_H
 #define __HDLC_H
 
-#define GENERIC_HDLC_VERSION 4 /* For synchronization with sethdlc utility */
-
-#define CLOCK_DEFAULT   0      /* Default setting */
-#define CLOCK_EXT      1       /* External TX and RX clock - DTE */
-#define CLOCK_INT      2       /* Internal TX and RX clock - DCE */
-#define CLOCK_TXINT    3       /* Internal TX and external RX clock */
-#define CLOCK_TXFROMRX 4       /* TX clock derived from external RX clock */
-
-
-#define ENCODING_DEFAULT       0 /* Default setting */
-#define ENCODING_NRZ           1
-#define ENCODING_NRZI          2
-#define ENCODING_FM_MARK       3
-#define ENCODING_FM_SPACE      4
-#define ENCODING_MANCHESTER    5
-
-
-#define PARITY_DEFAULT         0 /* Default setting */
-#define PARITY_NONE            1 /* No parity */
-#define PARITY_CRC16_PR0       2 /* CRC16, initial value 0x0000 */
-#define PARITY_CRC16_PR1       3 /* CRC16, initial value 0xFFFF */
-#define PARITY_CRC16_PR0_CCITT 4 /* CRC16, initial 0x0000, ITU-T version */
-#define PARITY_CRC16_PR1_CCITT 5 /* CRC16, initial 0xFFFF, ITU-T version */
-#define PARITY_CRC32_PR0_CCITT 6 /* CRC32, initial value 0x00000000 */
-#define PARITY_CRC32_PR1_CCITT 7 /* CRC32, initial value 0xFFFFFFFF */
-
-#define LMI_DEFAULT            0 /* Default setting */
-#define LMI_NONE               1 /* No LMI, all PVCs are static */
-#define LMI_ANSI               2 /* ANSI Annex D */
-#define LMI_CCITT              3 /* ITU-T Annex A */
-#define LMI_CISCO              4 /* The "original" LMI, aka Gang of Four */
 
 #define HDLC_MAX_MTU 1500      /* Ethernet 1500 bytes */
+#if 0
 #define HDLC_MAX_MRU (HDLC_MAX_MTU + 10 + 14 + 4) /* for ETH+VLAN over FR */
+#else
+#define HDLC_MAX_MRU 1600 /* as required for FR network */
+#endif
 
 
 #ifdef __KERNEL__
 
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
-#include <net/syncppp.h>
 #include <linux/hdlc/ioctl.h>
 
 
-typedef struct {               /* Used in Cisco and PPP mode */
-       u8 address;
-       u8 control;
-       u16 protocol;
-}__attribute__ ((packed)) hdlc_header;
-
-
-
-typedef struct {
-       u32 type;               /* code */
-       u32 par1;
-       u32 par2;
-       u16 rel;                /* reliability */
-       u32 time;
-}__attribute__ ((packed)) cisco_packet;
-#define        CISCO_PACKET_LEN        18
-#define        CISCO_BIG_PACKET_LEN    20
-
-
-
-typedef struct pvc_device_struct {
-       struct net_device *master;
-       struct net_device *main;
-       struct net_device *ether; /* bridged Ethernet interface */
-       struct pvc_device_struct *next; /* Sorted in ascending DLCI order */
-       int dlci;
-       int open_count;
-
-       struct {
-               unsigned int new: 1;
-               unsigned int active: 1;
-               unsigned int exist: 1;
-               unsigned int deleted: 1;
-               unsigned int fecn: 1;
-               unsigned int becn: 1;
-               unsigned int bandwidth; /* Cisco LMI reporting only */
-       }state;
-}pvc_device;
-
-
-
-typedef struct hdlc_device_struct {
-       /* To be initialized by hardware driver */
+/* Used by all network devices here, pointed to by netdev_priv(dev) */
+struct hdlc_device_desc {
+       int (*netif_rx)(struct sk_buff *skb);
        struct net_device_stats stats;
-
+};
+
+/* This structure is a private property of HDLC protocols.
+   Hardware drivers have no interest here */
+
+struct hdlc_proto {
+       int (*open)(struct net_device *dev);
+       void (*close)(struct net_device *dev);
+       void (*start)(struct net_device *dev); /* if open & DCD */
+       void (*stop)(struct net_device *dev); /* if open & !DCD */
+       void (*detach)(struct net_device *dev);
+       int (*ioctl)(struct net_device *dev, struct ifreq *ifr);
+       unsigned short (*type_trans)(struct sk_buff *skb,
+                                    struct net_device *dev);
+       struct module *module;
+       struct hdlc_proto *next; /* next protocol in the list */
+};
+
+
+typedef struct hdlc_device {
        /* used by HDLC layer to take control over HDLC device from hw driver*/
        int (*attach)(struct net_device *dev,
                      unsigned short encoding, unsigned short parity);
@@ -107,82 +58,18 @@ typedef struct hdlc_device_struct {
        /* hardware driver must handle this instead of dev->hard_start_xmit */
        int (*xmit)(struct sk_buff *skb, struct net_device *dev);
 
-
        /* Things below are for HDLC layer internal use only */
-       struct {
-               int (*open)(struct net_device *dev);
-               void (*close)(struct net_device *dev);
-
-               /* if open & DCD */
-               void (*start)(struct net_device *dev);
-               /* if open & !DCD */
-               void (*stop)(struct net_device *dev);
-
-               void (*detach)(struct hdlc_device_struct *hdlc);
-               int (*netif_rx)(struct sk_buff *skb);
-               unsigned short (*type_trans)(struct sk_buff *skb,
-                                            struct net_device *dev);
-               int id;         /* IF_PROTO_HDLC/CISCO/FR/etc. */
-       }proto;
-
+       const struct hdlc_proto *proto;
        int carrier;
        int open;
        spinlock_t state_lock;
-
-       union {
-               struct {
-                       fr_proto settings;
-                       pvc_device *first_pvc;
-                       int dce_pvc_count;
-
-                       struct timer_list timer;
-                       unsigned long last_poll;
-                       int reliable;
-                       int dce_changed;
-                       int request;
-                       int fullrep_sent;
-                       u32 last_errors; /* last errors bit list */
-                       u8 n391cnt;
-                       u8 txseq; /* TX sequence number */
-                       u8 rxseq; /* RX sequence number */
-               }fr;
-
-               struct {
-                       cisco_proto settings;
-
-                       struct timer_list timer;
-                       unsigned long last_poll;
-                       int up;
-                       int request_sent;
-                       u32 txseq; /* TX sequence number */
-                       u32 rxseq; /* RX sequence number */
-               }cisco;
-
-               struct {
-                       raw_hdlc_proto settings;
-               }raw_hdlc;
-
-               struct {
-                       struct ppp_device pppdev;
-                       struct ppp_device *syncppp_ptr;
-                       int (*old_change_mtu)(struct net_device *dev,
-                                             int new_mtu);
-               }ppp;
-       }state;
+       void *state;
        void *priv;
 }hdlc_device;
 
 
 
-int hdlc_raw_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_cisco_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_ppp_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr);
-int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr);
-
-
-/* Exported from hdlc.o */
+/* Exported from hdlc module */
 
 /* Called by hardware driver when a user requests HDLC service */
 int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
@@ -191,17 +78,21 @@ int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 #define register_hdlc_device(dev)      register_netdev(dev)
 void unregister_hdlc_device(struct net_device *dev);
 
+
+void register_hdlc_protocol(struct hdlc_proto *proto);
+void unregister_hdlc_protocol(struct hdlc_proto *proto);
+
 struct net_device *alloc_hdlcdev(void *priv);
 
-static __inline__ hdlc_device* dev_to_hdlc(struct net_device *dev)
+
+static __inline__ struct hdlc_device_desc* dev_to_desc(struct net_device *dev)
 {
        return netdev_priv(dev);
 }
 
-
-static __inline__ pvc_device* dev_to_pvc(struct net_device *dev)
+static __inline__ hdlc_device* dev_to_hdlc(struct net_device *dev)
 {
-       return (pvc_device*)dev->priv;
+       return netdev_priv(dev) + sizeof(struct hdlc_device_desc);
 }
 
 
@@ -225,18 +116,14 @@ int hdlc_open(struct net_device *dev);
 /* Must be called by hardware driver when HDLC device is being closed */
 void hdlc_close(struct net_device *dev);
 
+int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
+                        int (*rx)(struct sk_buff *skb), size_t size);
 /* May be used by hardware driver to gain control over HDLC device */
-static __inline__ void hdlc_proto_detach(hdlc_device *hdlc)
-{
-       if (hdlc->proto.detach)
-               hdlc->proto.detach(hdlc);
-       hdlc->proto.detach = NULL;
-}
-
+void detach_hdlc_protocol(struct net_device *dev);
 
 static __inline__ struct net_device_stats *hdlc_stats(struct net_device *dev)
 {
-       return &dev_to_hdlc(dev)->stats;
+       return &dev_to_desc(dev)->stats;
 }
 
 
@@ -248,8 +135,8 @@ static __inline__ __be16 hdlc_type_trans(struct sk_buff *skb,
        skb->mac.raw  = skb->data;
        skb->dev      = dev;
 
-       if (hdlc->proto.type_trans)
-               return hdlc->proto.type_trans(skb, dev);
+       if (hdlc->proto->type_trans)
+               return hdlc->proto->type_trans(skb, dev);
        else
                return htons(ETH_P_HDLC);
 }
index 78430ba3ea69ecb6adbcf31888473a867529af8f..583972364357764ec38d4ef91a95b080ed808659 100644 (file)
@@ -1,6 +1,39 @@
 #ifndef __HDLC_IOCTL_H__
 #define __HDLC_IOCTL_H__
 
+
+#define GENERIC_HDLC_VERSION 4 /* For synchronization with sethdlc utility */
+
+#define CLOCK_DEFAULT   0      /* Default setting */
+#define CLOCK_EXT      1       /* External TX and RX clock - DTE */
+#define CLOCK_INT      2       /* Internal TX and RX clock - DCE */
+#define CLOCK_TXINT    3       /* Internal TX and external RX clock */
+#define CLOCK_TXFROMRX 4       /* TX clock derived from external RX clock */
+
+
+#define ENCODING_DEFAULT       0 /* Default setting */
+#define ENCODING_NRZ           1
+#define ENCODING_NRZI          2
+#define ENCODING_FM_MARK       3
+#define ENCODING_FM_SPACE      4
+#define ENCODING_MANCHESTER    5
+
+
+#define PARITY_DEFAULT         0 /* Default setting */
+#define PARITY_NONE            1 /* No parity */
+#define PARITY_CRC16_PR0       2 /* CRC16, initial value 0x0000 */
+#define PARITY_CRC16_PR1       3 /* CRC16, initial value 0xFFFF */
+#define PARITY_CRC16_PR0_CCITT 4 /* CRC16, initial 0x0000, ITU-T version */
+#define PARITY_CRC16_PR1_CCITT 5 /* CRC16, initial 0xFFFF, ITU-T version */
+#define PARITY_CRC32_PR0_CCITT 6 /* CRC32, initial value 0x00000000 */
+#define PARITY_CRC32_PR1_CCITT 7 /* CRC32, initial value 0xFFFFFFFF */
+
+#define LMI_DEFAULT            0 /* Default setting */
+#define LMI_NONE               1 /* No LMI, all PVCs are static */
+#define LMI_ANSI               2 /* ANSI Annex D */
+#define LMI_CCITT              3 /* ITU-T Annex A */
+#define LMI_CISCO              4 /* The "original" LMI, aka Gang of Four */
+
 typedef struct { 
        unsigned int clock_rate; /* bits per second */
        unsigned int clock_type; /* internal, external, TX-internal etc. */
index c0e7fab28ce345dc0c48c0a430fc640077caa181..c8f8df25c7e0faa1e19ef06e53bdc4d5442d573c 100644 (file)
@@ -40,7 +40,6 @@ struct i2c_algo_bit_data {
        /* local settings */
        int udelay;             /* half-clock-cycle time in microsecs */
                                /* i.e. clock is (500 / udelay) KHz */
-       int mdelay;             /* in millisecs, unused */
        int timeout;            /* in jiffies */
 };
 
index 18b0adf57a3d7d9ca26ac8b2ece2187fe9f35b2b..9908f3fc48396289f9d831c1ae33e4a4a26db932 100644 (file)
@@ -35,7 +35,6 @@ struct i2c_algo_pcf_data {
 
        /* local settings */
        int udelay;
-       int mdelay;
        int timeout;
 };
 
diff --git a/include/linux/i2c-algo-sibyte.h b/include/linux/i2c-algo-sibyte.h
deleted file mode 100644 (file)
index 03914de..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2001,2002,2003 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by 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 I2C_ALGO_SIBYTE_H
-#define I2C_ALGO_SIBYTE_H 1
-
-#include <linux/i2c.h>
-
-struct i2c_algo_sibyte_data {
-       void *data;             /* private data */
-        int   bus;             /* which bus */
-        void *reg_base;                /* CSR base */
-};
-
-int i2c_sibyte_add_bus(struct i2c_adapter *, int speed);
-int i2c_sibyte_del_bus(struct i2c_adapter *);
-
-#endif /* I2C_ALGO_SIBYTE_H */
index eb0628a7ecc637ec71e18714105ac814f679f718..9b5d04768c2c103b1b745ab329ce3e19ded36e1d 100644 (file)
@@ -64,14 +64,6 @@ extern int i2c_master_recv(struct i2c_client *,char* ,int);
  */
 extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
 
-/*
- * Some adapter types (i.e. PCF 8584 based ones) may support slave behaviuor. 
- * This is not tested/implemented yet and will change in the future.
- */
-extern int i2c_slave_send(struct i2c_client *,char*,int);
-extern int i2c_slave_recv(struct i2c_client *,char*,int);
-
-
 
 /* This is the very generalized SMBus access routine. You probably do not
    want to use this, though; one of the functions below may be much easier,
@@ -201,10 +193,6 @@ struct i2c_algorithm {
                           unsigned short flags, char read_write,
                           u8 command, int size, union i2c_smbus_data * data);
 
-       /* --- these optional/future use for some adapter types.*/
-       int (*slave_send)(struct i2c_adapter *,char*,int);
-       int (*slave_recv)(struct i2c_adapter *,char*,int);
-
        /* --- ioctl like call to set div. parameters. */
        int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long);
 
@@ -220,7 +208,7 @@ struct i2c_adapter {
        struct module *owner;
        unsigned int id;
        unsigned int class;
-       struct i2c_algorithm *algo;/* the algorithm to access the bus   */
+       const struct i2c_algorithm *algo; /* the algorithm to access the bus */
        void *algo_data;
 
        /* --- administration stuff. */
index cd080d76532477f5dbbf71965e74243fd422bf39..8018c2e22c0c3c6bdf237378cc18f15668eb89e4 100644 (file)
@@ -59,6 +59,8 @@
 #define IFF_SLAVE_INACTIVE     0x4     /* bonding slave not the curr. active */
 #define IFF_MASTER_8023AD      0x8     /* bonding master, 802.3ad.     */
 #define IFF_MASTER_ALB 0x10            /* bonding master, balance-alb. */
+#define IFF_BONDING    0x20            /* bonding master or slave      */
+#define IFF_SLAVE_NEEDARP 0x40         /* need ARPs for validation     */
 
 #define IF_GET_IFACE   0x0001          /* for querying only */
 #define IF_GET_PROTO   0x0002
index 6667785dd1ff22d7452b716b380e7475158ee8b9..e92b1455d7afd8c908bfc0722be018a09c46c226 100644 (file)
@@ -68,6 +68,7 @@ extern initcall_t __security_initcall_start[], __security_initcall_end[];
 
 /* Defined in init/main.c */
 extern char saved_command_line[];
+extern unsigned int reset_devices;
 
 /* used by init/main.c */
 extern void setup_arch(char **);
index a04c154c5207954c39d58ba2ce95169b37ea57ae..a6d9daa38c6d4da99fa6f6bffe9b99a5c6c79ae0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * linux/include/linux/jbd.h
- * 
+ *
  * Written by Stephen C. Tweedie <sct@redhat.com>
  *
  * Copyright 1998-2000 Red Hat, Inc --- All Rights Reserved
@@ -64,7 +64,7 @@ extern int journal_enable_debug;
                if ((n) <= journal_enable_debug) {                      \
                        printk (KERN_DEBUG "(%s, %d): %s: ",            \
                                __FILE__, __LINE__, __FUNCTION__);      \
-                       printk (f, ## a);                               \
+                       printk (f, ## a);                               \
                }                                                       \
        } while (0)
 #else
@@ -97,8 +97,8 @@ extern void jbd_slab_free(void *ptr, size_t size);
  * number of outstanding buffers possible at any time.  When the
  * operation completes, any buffer credits not used are credited back to
  * the transaction, so that at all times we know how many buffers the
- * outstanding updates on a transaction might possibly touch. 
- * 
+ * outstanding updates on a transaction might possibly touch.
+ *
  * This is an opaque datatype.
  **/
 typedef struct handle_s                handle_t;       /* Atomic operation type */
@@ -108,7 +108,7 @@ typedef struct handle_s             handle_t;       /* Atomic operation type */
  * typedef journal_t - The journal_t maintains all of the journaling state information for a single filesystem.
  *
  * journal_t is linked to from the fs superblock structure.
- * 
+ *
  * We use the journal_t to keep track of all outstanding transaction
  * activity on the filesystem, and to manage the state of the log
  * writing process.
@@ -128,7 +128,7 @@ typedef struct journal_s    journal_t;      /* Journal control structure */
  * On-disk structures
  */
 
-/* 
+/*
  * Descriptor block types:
  */
 
@@ -149,8 +149,8 @@ typedef struct journal_header_s
 } journal_header_t;
 
 
-/* 
- * The block tag: used to describe a single buffer in the journal 
+/*
+ * The block tag: used to describe a single buffer in the journal
  */
 typedef struct journal_block_tag_s
 {
@@ -158,9 +158,9 @@ typedef struct journal_block_tag_s
        __be32          t_flags;        /* See below */
 } journal_block_tag_t;
 
-/* 
+/*
  * The revoke descriptor: used on disk to describe a series of blocks to
- * be revoked from the log 
+ * be revoked from the log
  */
 typedef struct journal_revoke_header_s
 {
@@ -201,9 +201,9 @@ typedef struct journal_superblock_s
 
 /* 0x0024 */
        /* Remaining fields are only valid in a version-2 superblock */
-       __be32  s_feature_compat;       /* compatible feature set */
-       __be32  s_feature_incompat;     /* incompatible feature set */
-       __be32  s_feature_ro_compat;    /* readonly-compatible feature set */
+       __be32  s_feature_compat;       /* compatible feature set */
+       __be32  s_feature_incompat;     /* incompatible feature set */
+       __be32  s_feature_ro_compat;    /* readonly-compatible feature set */
 /* 0x0030 */
        __u8    s_uuid[16];             /* 128-bit uuid for journal */
 
@@ -374,10 +374,10 @@ struct jbd_revoke_table_s;
  **/
 
 /* Docbook can't yet cope with the bit fields, but will leave the documentation
- * in so it can be fixed later. 
+ * in so it can be fixed later.
  */
 
-struct handle_s 
+struct handle_s
 {
        /* Which compound transaction is this update a part of? */
        transaction_t           *h_transaction;
@@ -435,7 +435,7 @@ struct handle_s
  *
  */
 
-struct transaction_s 
+struct transaction_s
 {
        /* Pointer to the journal for this transaction. [no locking] */
        journal_t               *t_journal;
@@ -455,7 +455,7 @@ struct transaction_s
                T_RUNDOWN,
                T_FLUSH,
                T_COMMIT,
-               T_FINISHED 
+               T_FINISHED
        }                       t_state;
 
        /*
@@ -569,7 +569,7 @@ struct transaction_s
  *     journal_t.
  * @j_flags:  General journaling state flags
  * @j_errno:  Is there an outstanding uncleared error on the journal (from a
- *     prior abort)? 
+ *     prior abort)?
  * @j_sb_buffer: First part of superblock buffer
  * @j_superblock: Second part of superblock buffer
  * @j_format_version: Version of the superblock format
@@ -583,7 +583,7 @@ struct transaction_s
  * @j_wait_transaction_locked: Wait queue for waiting for a locked transaction
  *  to start committing, or for a barrier lock to be released
  * @j_wait_logspace: Wait queue for waiting for checkpointing to complete
- * @j_wait_done_commit: Wait queue for waiting for commit to complete 
+ * @j_wait_done_commit: Wait queue for waiting for commit to complete
  * @j_wait_checkpoint:  Wait queue to trigger checkpointing
  * @j_wait_commit: Wait queue to trigger commit
  * @j_wait_updates: Wait queue to wait for updates to complete
@@ -592,7 +592,7 @@ struct transaction_s
  * @j_tail: Journal tail - identifies the oldest still-used block in the
  *  journal.
  * @j_free: Journal free - how many free blocks are there in the journal?
- * @j_first: The block number of the first usable block 
+ * @j_first: The block number of the first usable block
  * @j_last: The block number one beyond the last usable block
  * @j_dev: Device where we store the journal
  * @j_blocksize: blocksize for the location where we store the journal.
@@ -604,12 +604,12 @@ struct transaction_s
  * @j_list_lock: Protects the buffer lists and internal buffer state.
  * @j_inode: Optional inode where we store the journal.  If present, all journal
  *     block numbers are mapped into this inode via bmap().
- * @j_tail_sequence:  Sequence number of the oldest transaction in the log 
+ * @j_tail_sequence:  Sequence number of the oldest transaction in the log
  * @j_transaction_sequence: Sequence number of the next transaction to grant
  * @j_commit_sequence: Sequence number of the most recently committed
  *  transaction
  * @j_commit_request: Sequence number of the most recent transaction wanting
- *     commit 
+ *     commit
  * @j_uuid: Uuid of client object.
  * @j_task: Pointer to the current commit thread for this journal
  * @j_max_transaction_buffers:  Maximum number of metadata buffers to allow in a
@@ -699,7 +699,7 @@ struct journal_s
        wait_queue_head_t       j_wait_updates;
 
        /* Semaphore for locking against concurrent checkpoints */
-       struct mutex            j_checkpoint_mutex;
+       struct mutex            j_checkpoint_mutex;
 
        /*
         * Journal head: identifies the first unused block in the journal.
@@ -732,7 +732,7 @@ struct journal_s
         */
        struct block_device     *j_dev;
        int                     j_blocksize;
-       unsigned int            j_blk_offset;
+       unsigned long           j_blk_offset;
 
        /*
         * Device which holds the client fs.  For internal journal this will be
@@ -823,8 +823,8 @@ struct journal_s
        void *j_private;
 };
 
-/* 
- * Journal flag definitions 
+/*
+ * Journal flag definitions
  */
 #define JFS_UNMOUNT    0x001   /* Journal thread is being destroyed */
 #define JFS_ABORT      0x002   /* Journaling has been aborted for errors. */
@@ -833,7 +833,7 @@ struct journal_s
 #define JFS_LOADED     0x010   /* The journal superblock has been loaded */
 #define JFS_BARRIER    0x020   /* Use IDE barriers */
 
-/* 
+/*
  * Function declarations for the journaling transaction and buffer
  * management
  */
@@ -862,11 +862,11 @@ int __journal_remove_checkpoint(struct journal_head *);
 void __journal_insert_checkpoint(struct journal_head *, transaction_t *);
 
 /* Buffer IO */
-extern int 
+extern int
 journal_write_metadata_buffer(transaction_t      *transaction,
                              struct journal_head  *jh_in,
                              struct journal_head **jh_out,
-                             int                  blocknr);
+                             unsigned long        blocknr);
 
 /* Transaction locking */
 extern void            __wait_on_journal (journal_t *);
@@ -890,7 +890,7 @@ static inline handle_t *journal_current_handle(void)
 /* The journaling code user interface:
  *
  * Create and destroy handles
- * Register buffer modifications against the current transaction. 
+ * Register buffer modifications against the current transaction.
  */
 
 extern handle_t *journal_start(journal_t *, int nblocks);
@@ -917,11 +917,11 @@ extern journal_t * journal_init_dev(struct block_device *bdev,
                                int start, int len, int bsize);
 extern journal_t * journal_init_inode (struct inode *);
 extern int        journal_update_format (journal_t *);
-extern int        journal_check_used_features 
+extern int        journal_check_used_features
                   (journal_t *, unsigned long, unsigned long, unsigned long);
-extern int        journal_check_available_features 
+extern int        journal_check_available_features
                   (journal_t *, unsigned long, unsigned long, unsigned long);
-extern int        journal_set_features 
+extern int        journal_set_features
                   (journal_t *, unsigned long, unsigned long, unsigned long);
 extern int        journal_create     (journal_t *);
 extern int        journal_load       (journal_t *journal);
@@ -1015,7 +1015,7 @@ do {                                                                         \
  * bit, when set, indicates that we have had a fatal error somewhere,
  * either inside the journaling layer or indicated to us by the client
  * (eg. ext3), and that we and should not commit any further
- * transactions.  
+ * transactions.
  */
 
 static inline int is_journal_aborted(journal_t *journal)
@@ -1082,7 +1082,7 @@ static inline int jbd_space_needed(journal_t *journal)
 #define BJ_Reserved    7       /* Buffer is reserved for access by journal */
 #define BJ_Locked      8       /* Locked for I/O during commit */
 #define BJ_Types       9
+
 extern int jbd_blocks_per_page(struct inode *inode);
 
 #ifdef __KERNEL__
index 329ebcffa106801f012472e281840c4756382f9e..c8d5f207c3d4892cf23fc4ebd24b736b4023779a 100644 (file)
@@ -115,6 +115,21 @@ static inline u64 get_jiffies_64(void)
         ((long)(a) - (long)(b) >= 0))
 #define time_before_eq(a,b)    time_after_eq(b,a)
 
+/* Same as above, but does so with platform independent 64bit types.
+ * These must be used when utilizing jiffies_64 (i.e. return value of
+ * get_jiffies_64() */
+#define time_after64(a,b)      \
+       (typecheck(__u64, a) && \
+        typecheck(__u64, b) && \
+        ((__s64)(b) - (__s64)(a) < 0))
+#define time_before64(a,b)     time_after64(b,a)
+
+#define time_after_eq64(a,b)   \
+       (typecheck(__u64, a) && \
+        typecheck(__u64, b) && \
+        ((__s64)(a) - (__s64)(b) >= 0))
+#define time_before_eq64(a,b)  time_after_eq64(b,a)
+
 /*
  * Have the 32 bit jiffies value wrap 5 minutes after boot
  * so jiffies wrap bugs show up earlier.
index e44a37e2c71c60d4c45f6bb16729961a974c2c21..4d00988dad039ebc5f871d6323b2b7d1676da9dc 100644 (file)
@@ -187,6 +187,7 @@ extern void bust_spinlocks(int yes);
 extern int oops_in_progress;           /* If set, an oops, panic(), BUG() or die() is in progress */
 extern int panic_timeout;
 extern int panic_on_oops;
+extern int panic_on_unrecovered_nmi;
 extern int tainted;
 extern const char *print_tainted(void);
 extern void add_taint(unsigned);
@@ -349,4 +350,11 @@ struct sysinfo {
 /* Trap pasters of __FUNCTION__ at compile-time */
 #define __FUNCTION__ (__func__)
 
+/* This helps us to avoid #ifdef CONFIG_NUMA */
+#ifdef CONFIG_NUMA
+#define NUMA_BUILD 1
+#else
+#define NUMA_BUILD 0
+#endif
+
 #endif
index 2d229327959ed9809042af03c8fdb917913e000e..bcd9cd173c2c80ffce52af4ea925c24e7f22dc0f 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/sysfs.h>
+#include <linux/compiler.h>
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
 #include <linux/kref.h>
@@ -71,12 +72,12 @@ static inline const char * kobject_name(const struct kobject * kobj)
 extern void kobject_init(struct kobject *);
 extern void kobject_cleanup(struct kobject *);
 
-extern int kobject_add(struct kobject *);
+extern int __must_check kobject_add(struct kobject *);
 extern void kobject_del(struct kobject *);
 
-extern int kobject_rename(struct kobject *, const char *new_name);
+extern int __must_check kobject_rename(struct kobject *, const char *new_name);
 
-extern int kobject_register(struct kobject *);
+extern int __must_check kobject_register(struct kobject *);
 extern void kobject_unregister(struct kobject *);
 
 extern struct kobject * kobject_get(struct kobject *);
@@ -128,8 +129,8 @@ struct kset {
 
 
 extern void kset_init(struct kset * k);
-extern int kset_add(struct kset * k);
-extern int kset_register(struct kset * k);
+extern int __must_check kset_add(struct kset * k);
+extern int __must_check kset_register(struct kset * k);
 extern void kset_unregister(struct kset * k);
 
 static inline struct kset * to_kset(struct kobject * kobj)
@@ -239,7 +240,7 @@ extern struct subsystem hypervisor_subsys;
        (obj)->subsys.kset.kobj.kset = &(_subsys).kset
 
 extern void subsystem_init(struct subsystem *);
-extern int subsystem_register(struct subsystem *);
+extern int __must_check subsystem_register(struct subsystem *);
 extern void subsystem_unregister(struct subsystem *);
 
 static inline struct subsystem * subsys_get(struct subsystem * s)
@@ -258,7 +259,8 @@ struct subsys_attribute {
        ssize_t (*store)(struct subsystem *, const char *, size_t); 
 };
 
-extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
+extern int __must_check subsys_create_file(struct subsystem * ,
+                                       struct subsys_attribute *);
 
 #if defined(CONFIG_HOTPLUG)
 void kobject_uevent(struct kobject *kobj, enum kobject_action action);
index 932021f872d5feaa71a38d872ab6dcce74f96158..6c9873f8828751d9c48c3c2a5b0eeef793855233 100644 (file)
 #endif
 
 #define KPROBE_ENTRY(name) \
-  .section .kprobes.text, "ax"; \
+  .pushsection .kprobes.text, "ax"; \
   ENTRY(name)
 
+#define KPROBE_END(name) \
+  END(name);            \
+  .popsection
+
 #ifndef END
 #define END(name) \
   .size name, .-name
index 856f0ee7e84ab53370f6df38d791547bfbfdcaa8..7b703b6d43582dd918a1c8c397a2a3932accf72c 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/mutex.h>
 #include <linux/debug_locks.h>
 #include <linux/backing-dev.h>
+#include <linux/mm_types.h>
 
 struct mempolicy;
 struct anon_vma;
@@ -198,6 +199,7 @@ struct vm_operations_struct {
        void (*open)(struct vm_area_struct * area);
        void (*close)(struct vm_area_struct * area);
        struct page * (*nopage)(struct vm_area_struct * area, unsigned long address, int *type);
+       unsigned long (*nopfn)(struct vm_area_struct * area, unsigned long address);
        int (*populate)(struct vm_area_struct * area, unsigned long address, unsigned long len, pgprot_t prot, unsigned long pgoff, int nonblock);
 
        /* notification that a previously read-only page is about to become
@@ -215,62 +217,6 @@ struct vm_operations_struct {
 struct mmu_gather;
 struct inode;
 
-/*
- * Each physical page in the system has a struct page associated with
- * it to keep track of whatever it is we are using the page for at the
- * moment. Note that we have no way to track which tasks are using
- * a page, though if it is a pagecache page, rmap structures can tell us
- * who is mapping it.
- */
-struct page {
-       unsigned long flags;            /* Atomic flags, some possibly
-                                        * updated asynchronously */
-       atomic_t _count;                /* Usage count, see below. */
-       atomic_t _mapcount;             /* Count of ptes mapped in mms,
-                                        * to show when page is mapped
-                                        * & limit reverse map searches.
-                                        */
-       union {
-           struct {
-               unsigned long private;          /* Mapping-private opaque data:
-                                                * usually used for buffer_heads
-                                                * if PagePrivate set; used for
-                                                * swp_entry_t if PageSwapCache;
-                                                * indicates order in the buddy
-                                                * system if PG_buddy is set.
-                                                */
-               struct address_space *mapping;  /* If low bit clear, points to
-                                                * inode address_space, or NULL.
-                                                * If page mapped as anonymous
-                                                * memory, low bit is set, and
-                                                * it points to anon_vma object:
-                                                * see PAGE_MAPPING_ANON below.
-                                                */
-           };
-#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
-           spinlock_t ptl;
-#endif
-       };
-       pgoff_t index;                  /* Our offset within mapping. */
-       struct list_head lru;           /* Pageout list, eg. active_list
-                                        * protected by zone->lru_lock !
-                                        */
-       /*
-        * On machines where all RAM is mapped into kernel address space,
-        * we can simply calculate the virtual address. On machines with
-        * highmem some memory is mapped into kernel virtual memory
-        * dynamically, so we need a place to store that address.
-        * Note that this field could be 16 bits on x86 ... ;)
-        *
-        * Architectures with slow multiplication can define
-        * WANT_PAGE_VIRTUAL in asm/page.h
-        */
-#if defined(WANT_PAGE_VIRTUAL)
-       void *virtual;                  /* Kernel virtual address (NULL if
-                                          not kmapped, ie. highmem) */
-#endif /* WANT_PAGE_VIRTUAL */
-};
-
 #define page_private(page)             ((page)->private)
 #define set_page_private(page, v)      ((page)->private = (v))
 
@@ -501,7 +447,11 @@ static inline struct zone *page_zone(struct page *page)
 
 static inline unsigned long zone_to_nid(struct zone *zone)
 {
-       return zone->zone_pgdat->node_id;
+#ifdef CONFIG_NUMA
+       return zone->node;
+#else
+       return 0;
+#endif
 }
 
 static inline unsigned long page_to_nid(struct page *page)
@@ -546,11 +496,6 @@ static inline void set_page_links(struct page *page, enum zone_type zone,
  */
 #include <linux/vmstat.h>
 
-#ifndef CONFIG_DISCONTIGMEM
-/* The array of struct pages - for discontigmem use pgdat->lmem_map */
-extern struct page *mem_map;
-#endif
-
 static __always_inline void *lowmem_page_address(struct page *page)
 {
        return __va(page_to_pfn(page) << PAGE_SHIFT);
@@ -649,6 +594,12 @@ static inline int page_mapped(struct page *page)
 #define NOPAGE_SIGBUS  (NULL)
 #define NOPAGE_OOM     ((struct page *) (-1))
 
+/*
+ * Error return values for the *_nopfn functions
+ */
+#define NOPFN_SIGBUS   ((unsigned long) -1)
+#define NOPFN_OOM      ((unsigned long) -2)
+
 /*
  * Different kinds of faults, as returned by handle_mm_fault().
  * Used to decide whether a process gets delivered SIGBUS or
@@ -937,6 +888,56 @@ extern void free_area_init(unsigned long * zones_size);
 extern void free_area_init_node(int nid, pg_data_t *pgdat,
        unsigned long * zones_size, unsigned long zone_start_pfn, 
        unsigned long *zholes_size);
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+/*
+ * With CONFIG_ARCH_POPULATES_NODE_MAP set, an architecture may initialise its
+ * zones, allocate the backing mem_map and account for memory holes in a more
+ * architecture independent manner. This is a substitute for creating the
+ * zone_sizes[] and zholes_size[] arrays and passing them to
+ * free_area_init_node()
+ *
+ * An architecture is expected to register range of page frames backed by
+ * physical memory with add_active_range() before calling
+ * free_area_init_nodes() passing in the PFN each zone ends at. At a basic
+ * usage, an architecture is expected to do something like
+ *
+ * unsigned long max_zone_pfns[MAX_NR_ZONES] = {max_dma, max_normal_pfn,
+ *                                                      max_highmem_pfn};
+ * for_each_valid_physical_page_range()
+ *     add_active_range(node_id, start_pfn, end_pfn)
+ * free_area_init_nodes(max_zone_pfns);
+ *
+ * If the architecture guarantees that there are no holes in the ranges
+ * registered with add_active_range(), free_bootmem_active_regions()
+ * will call free_bootmem_node() for each registered physical page range.
+ * Similarly sparse_memory_present_with_active_regions() calls
+ * memory_present() for each range when SPARSEMEM is enabled.
+ *
+ * See mm/page_alloc.c for more information on each function exposed by
+ * CONFIG_ARCH_POPULATES_NODE_MAP
+ */
+extern void free_area_init_nodes(unsigned long *max_zone_pfn);
+extern void add_active_range(unsigned int nid, unsigned long start_pfn,
+                                       unsigned long end_pfn);
+extern void shrink_active_range(unsigned int nid, unsigned long old_end_pfn,
+                                               unsigned long new_end_pfn);
+extern void push_node_boundaries(unsigned int nid, unsigned long start_pfn,
+                                       unsigned long end_pfn);
+extern void remove_all_active_ranges(void);
+extern unsigned long absent_pages_in_range(unsigned long start_pfn,
+                                               unsigned long end_pfn);
+extern void get_pfn_range_for_nid(unsigned int nid,
+                       unsigned long *start_pfn, unsigned long *end_pfn);
+extern unsigned long find_min_pfn_with_active_regions(void);
+extern unsigned long find_max_pfn_with_active_regions(void);
+extern void free_bootmem_with_active_regions(int nid,
+                                               unsigned long max_low_pfn);
+extern void sparse_memory_present_with_active_regions(int nid);
+#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+extern int early_pfn_to_nid(unsigned long pfn);
+#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
+extern void set_dma_reserve(unsigned long new_dma_reserve);
 extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long);
 extern void setup_per_zone_pages_min(void);
 extern void mem_init(void);
@@ -1130,7 +1131,7 @@ void drop_slab(void);
 extern int randomize_va_space;
 #endif
 
-const char *arch_vma_name(struct vm_area_struct *vma);
+__attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma);
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
new file mode 100644 (file)
index 0000000..c3852fd
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef _LINUX_MM_TYPES_H
+#define _LINUX_MM_TYPES_H
+
+#include <linux/types.h>
+#include <linux/threads.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+
+struct address_space;
+
+/*
+ * Each physical page in the system has a struct page associated with
+ * it to keep track of whatever it is we are using the page for at the
+ * moment. Note that we have no way to track which tasks are using
+ * a page, though if it is a pagecache page, rmap structures can tell us
+ * who is mapping it.
+ */
+struct page {
+       unsigned long flags;            /* Atomic flags, some possibly
+                                        * updated asynchronously */
+       atomic_t _count;                /* Usage count, see below. */
+       atomic_t _mapcount;             /* Count of ptes mapped in mms,
+                                        * to show when page is mapped
+                                        * & limit reverse map searches.
+                                        */
+       union {
+           struct {
+               unsigned long private;          /* Mapping-private opaque data:
+                                                * usually used for buffer_heads
+                                                * if PagePrivate set; used for
+                                                * swp_entry_t if PageSwapCache;
+                                                * indicates order in the buddy
+                                                * system if PG_buddy is set.
+                                                */
+               struct address_space *mapping;  /* If low bit clear, points to
+                                                * inode address_space, or NULL.
+                                                * If page mapped as anonymous
+                                                * memory, low bit is set, and
+                                                * it points to anon_vma object:
+                                                * see PAGE_MAPPING_ANON below.
+                                                */
+           };
+#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS
+           spinlock_t ptl;
+#endif
+       };
+       pgoff_t index;                  /* Our offset within mapping. */
+       struct list_head lru;           /* Pageout list, eg. active_list
+                                        * protected by zone->lru_lock !
+                                        */
+       /*
+        * On machines where all RAM is mapped into kernel address space,
+        * we can simply calculate the virtual address. On machines with
+        * highmem some memory is mapped into kernel virtual memory
+        * dynamically, so we need a place to store that address.
+        * Note that this field could be 16 bits on x86 ... ;)
+        *
+        * Architectures with slow multiplication can define
+        * WANT_PAGE_VIRTUAL in asm/page.h
+        */
+#if defined(WANT_PAGE_VIRTUAL)
+       void *virtual;                  /* Kernel virtual address (NULL if
+                                          not kmapped, ie. highmem) */
+#endif /* WANT_PAGE_VIRTUAL */
+};
+
+#endif /* _LINUX_MM_TYPES_H */
index 3693f1a5278839c23243691564a5085af0617313..59855b8718a0a4b993a39cb825034ad081dd09cd 100644 (file)
@@ -58,6 +58,7 @@ enum zone_stat_item {
        NR_WRITEBACK,
        NR_UNSTABLE_NFS,        /* NFS unstable pages */
        NR_BOUNCE,
+       NR_VMSCAN_WRITE,
 #ifdef CONFIG_NUMA
        NUMA_HIT,               /* allocated in intended node */
        NUMA_MISS,              /* allocated in non intended node */
@@ -167,6 +168,7 @@ struct zone {
        unsigned long           lowmem_reserve[MAX_NR_ZONES];
 
 #ifdef CONFIG_NUMA
+       int node;
        /*
         * zone reclaim becomes active if more unmapped pages exist.
         */
@@ -305,6 +307,18 @@ struct zonelist {
        struct zone *zones[MAX_NUMNODES * MAX_NR_ZONES + 1]; // NULL delimited
 };
 
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+struct node_active_region {
+       unsigned long start_pfn;
+       unsigned long end_pfn;
+       int nid;
+};
+#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
+
+#ifndef CONFIG_DISCONTIGMEM
+/* The array of struct pages - for discontigmem use pgdat->lmem_map */
+extern struct page *mem_map;
+#endif
 
 /*
  * The pg_data_t structure is used in machines with CONFIG_DISCONTIGMEM
@@ -518,7 +532,8 @@ extern struct zone *next_zone(struct zone *zone);
 
 #endif
 
-#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+#if !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) && \
+       !defined(CONFIG_ARCH_POPULATES_NODE_MAP)
 #define early_pfn_to_nid(nid)  (0UL)
 #endif
 
index f7ca0b09075d960d54315b20c2f2cb1e29e3ec94..e0c393cc724048696b43e0ac4b2af04c3053cca3 100644 (file)
@@ -308,4 +308,16 @@ struct input_device_id {
        kernel_ulong_t driver_info;
 };
 
+/* EISA */
+
+#define EISA_SIG_LEN   8
+
+/* The EISA signature, in ASCII form, null terminated */
+struct eisa_device_id {
+       char          sig[EISA_SIG_LEN];
+       kernel_ulong_t driver_data;
+};
+
+#define EISA_DEVICE_MODALIAS_FMT "eisa:s%s"
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
index 43289127b458345334a961caa6bd269799f00aad..13d6d4eb8b3af70b008be76f6fcf3fc23dc602cb 100644 (file)
@@ -334,7 +334,6 @@ struct net_device
 
 
        struct net_device_stats* (*get_stats)(struct net_device *dev);
-       struct iw_statistics*   (*get_wireless_stats)(struct net_device *dev);
 
        /* List of functions to handle Wireless Extensions (instead of ioctl).
         * See <net/iw_handler.h> for details. Jean II */
@@ -1016,7 +1015,8 @@ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
 }
 
 /* On bonding slaves other than the currently active slave, suppress
- * duplicates except for 802.3ad ETH_P_SLOW and alb non-mcast/bcast.
+ * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
+ * ARP on active-backup slaves with arp_validate enabled.
  */
 static inline int skb_bond_should_drop(struct sk_buff *skb)
 {
@@ -1025,6 +1025,10 @@ static inline int skb_bond_should_drop(struct sk_buff *skb)
 
        if (master &&
            (dev->priv_flags & IFF_SLAVE_INACTIVE)) {
+               if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
+                   skb->protocol == __constant_htons(ETH_P_ARP))
+                       return 0;
+
                if (master->priv_flags & IFF_MASTER_ALB) {
                        if (skb->pkt_type != PACKET_BROADCAST &&
                            skb->pkt_type != PACKET_MULTICAST)
index 36f5bcf513b09496e14f1f5f7f1dae5877da1ea2..98c9b9f667a5690f34072e89fbf5508c1678db6e 100644 (file)
@@ -315,10 +315,6 @@ extern void nfs_end_data_update(struct inode *);
 extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
 extern void put_nfs_open_context(struct nfs_open_context *ctx);
 extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode);
-extern struct vfsmount *nfs_do_submount(const struct vfsmount *mnt_parent,
-                                       const struct dentry *dentry,
-                                       struct nfs_fh *fh,
-                                       struct nfs_fattr *fattr);
 
 /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
 extern u32 root_nfs_parse_addr(char *name); /*__init*/
index f9edcd2ff3c828c9496ca4da4f007d326e16ea4e..31a3cb617ce0b02c1129bcba8d58ff1c4bac000a 100644 (file)
@@ -269,14 +269,8 @@ fill_post_wcc(struct svc_fh *fhp)
        fhp->fh_post_uid        = inode->i_uid;
        fhp->fh_post_gid        = inode->i_gid;
        fhp->fh_post_size       = inode->i_size;
-       if (inode->i_blksize) {
-               fhp->fh_post_blksize    = inode->i_blksize;
-               fhp->fh_post_blocks     = inode->i_blocks;
-       } else {
-               fhp->fh_post_blksize    = BLOCK_SIZE;
-               /* how much do we care for accuracy with MinixFS? */
-               fhp->fh_post_blocks     = (inode->i_size+511) >> 9;
-       }
+       fhp->fh_post_blksize    = BLOCK_SIZE;
+       fhp->fh_post_blocks     = inode->i_blocks;
        fhp->fh_post_rdev[0]    = htonl((u32)imajor(inode));
        fhp->fh_post_rdev[1]    = htonl((u32)iminor(inode));
        fhp->fh_post_atime      = inode->i_atime;
index 8565b81d7fbcd9b440c88e1a6fdaabb7d99d1b67..5c3a4176eb64a732546e5ef6c75c61e06a7e1212 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/list.h>
+#include <linux/compiler.h>
 #include <linux/errno.h>
 #include <linux/device.h>
 
@@ -346,6 +347,8 @@ struct pci_driver {
        int  (*probe)  (struct pci_dev *dev, const struct pci_device_id *id);   /* New device inserted */
        void (*remove) (struct pci_dev *dev);   /* Device removed (NULL if not a hot-plug capable driver) */
        int  (*suspend) (struct pci_dev *dev, pm_message_t state);      /* Device suspended */
+       int  (*suspend_late) (struct pci_dev *dev, pm_message_t state);
+       int  (*resume_early) (struct pci_dev *dev);
        int  (*resume) (struct pci_dev *dev);                   /* Device woken up */
        int  (*enable_wake) (struct pci_dev *dev, pci_power_t state, int enable);   /* Enable wake event */
        void (*shutdown) (struct pci_dev *dev);
@@ -353,6 +356,8 @@ struct pci_driver {
        struct pci_error_handlers *err_handler;
        struct device_driver    driver;
        struct pci_dynids dynids;
+
+       int multithread_probe;
 };
 
 #define        to_pci_driver(drv) container_of(drv,struct pci_driver, driver)
@@ -401,7 +406,7 @@ extern struct list_head pci_root_buses;     /* list of all known PCI buses */
 extern struct list_head pci_devices;   /* list of all devices */
 
 void pcibios_fixup_bus(struct pci_bus *);
-int pcibios_enable_device(struct pci_dev *, int mask);
+int __must_check pcibios_enable_device(struct pci_dev *, int mask);
 char *pcibios_setup (char *str);
 
 /* Used only when drivers/pci/setup.c is used */
@@ -428,7 +433,7 @@ int pci_scan_slot(struct pci_bus *bus, int devfn);
 struct pci_dev * pci_scan_single_device(struct pci_bus *bus, int devfn);
 void pci_device_add(struct pci_dev *dev, struct pci_bus *bus);
 unsigned int pci_scan_child_bus(struct pci_bus *bus);
-void pci_bus_add_device(struct pci_dev *dev);
+int __must_check pci_bus_add_device(struct pci_dev *dev);
 void pci_read_bridge_bases(struct pci_bus *child);
 struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct resource *res);
 int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
@@ -436,6 +441,7 @@ extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
 extern void pci_dev_put(struct pci_dev *dev);
 extern void pci_remove_bus(struct pci_bus *b);
 extern void pci_remove_bus_device(struct pci_dev *dev);
+extern void pci_stop_bus_device(struct pci_dev *dev);
 void pci_setup_cardbus(struct pci_bus *bus);
 
 /* Generic PCI functions exported to card drivers */
@@ -488,19 +494,19 @@ static inline int pci_write_config_dword(struct pci_dev *dev, int where, u32 val
        return pci_bus_write_config_dword (dev->bus, dev->devfn, where, val);
 }
 
-int pci_enable_device(struct pci_dev *dev);
-int pci_enable_device_bars(struct pci_dev *dev, int mask);
+int __must_check pci_enable_device(struct pci_dev *dev);
+int __must_check pci_enable_device_bars(struct pci_dev *dev, int mask);
 void pci_disable_device(struct pci_dev *dev);
 void pci_set_master(struct pci_dev *dev);
 #define HAVE_PCI_SET_MWI
-int pci_set_mwi(struct pci_dev *dev);
+int __must_check pci_set_mwi(struct pci_dev *dev);
 void pci_clear_mwi(struct pci_dev *dev);
 void pci_intx(struct pci_dev *dev, int enable);
 int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
 int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
 void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
-int pci_assign_resource(struct pci_dev *dev, int i);
-int pci_assign_resource_fixed(struct pci_dev *dev, int i);
+int __must_check pci_assign_resource(struct pci_dev *dev, int i);
+int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i);
 void pci_restore_bars(struct pci_dev *dev);
 
 /* ROM control related routines */
@@ -526,23 +532,24 @@ void pdev_sort_resources(struct pci_dev *, struct resource_list *);
 void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
                    int (*)(struct pci_dev *, u8, u8));
 #define HAVE_PCI_REQ_REGIONS   2
-int pci_request_regions(struct pci_dev *, const char *);
+int __must_check pci_request_regions(struct pci_dev *, const char *);
 void pci_release_regions(struct pci_dev *);
-int pci_request_region(struct pci_dev *, int, const char *);
+int __must_check pci_request_region(struct pci_dev *, int, const char *);
 void pci_release_region(struct pci_dev *, int);
 
 /* drivers/pci/bus.c */
-int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
-                          resource_size_t size, resource_size_t align,
-                          resource_size_t min, unsigned int type_mask,
-                          void (*alignf)(void *, struct resource *,
-                                         resource_size_t, resource_size_t),
-                          void *alignf_data);
+int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
+                       struct resource *res, resource_size_t size,
+                       resource_size_t align, resource_size_t min,
+                       unsigned int type_mask,
+                       void (*alignf)(void *, struct resource *,
+                               resource_size_t, resource_size_t),
+                       void *alignf_data);
 void pci_enable_bridges(struct pci_bus *bus);
 
 /* Proper probing supporting hot-pluggable devices */
-int __pci_register_driver(struct pci_driver *, struct module *);
-static inline int pci_register_driver(struct pci_driver *driver)
+int __must_check __pci_register_driver(struct pci_driver *, struct module *);
+static inline int __must_check pci_register_driver(struct pci_driver *driver)
 {
        return __pci_register_driver(driver, THIS_MODULE);
 }
index 6a1e09834559a3b4945803debc64dab2d4363120..ab032ceafa84cfab770bbba5a4c8080c6dd12c4f 100644 (file)
 #define PCI_DEVICE_ID_SERVERWORKS_LE     0x0009
 #define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
 #define PCI_DEVICE_ID_SERVERWORKS_EPB    0x0103
+#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE  0x0132
 #define PCI_DEVICE_ID_SERVERWORKS_OSB4   0x0200
 #define PCI_DEVICE_ID_SERVERWORKS_CSB5   0x0201
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6    0x0203
 #define PCI_DEVICE_ID_MARVELL_GT64260  0x6430
 #define PCI_DEVICE_ID_MARVELL_MV64360  0x6460
 #define PCI_DEVICE_ID_MARVELL_MV64460  0x6480
-#define PCI_DEVICE_ID_MARVELL_GT96100  0x9652
-#define PCI_DEVICE_ID_MARVELL_GT96100A 0x9653
-
 
 #define PCI_VENDOR_ID_V3               0x11b0
 #define PCI_DEVICE_ID_V3_V960          0x0001
index 96930cb5927cddbf04852baca5c7aed50afd04ac..7d0e26cba42051d7230ec7d9ac1723c6569654ff 100644 (file)
 #define  PCI_CAP_ID_MSI                0x05    /* Message Signalled Interrupts */
 #define  PCI_CAP_ID_CHSWP      0x06    /* CompactPCI HotSwap */
 #define  PCI_CAP_ID_PCIX       0x07    /* PCI-X */
-#define  PCI_CAP_ID_HT_IRQCONF 0x08    /* HyperTransport IRQ Configuration */
+#define  PCI_CAP_ID_HT         0x08    /* HyperTransport */
 #define  PCI_CAP_ID_VNDR       0x09    /* Vendor specific capability */
 #define  PCI_CAP_ID_SHPC       0x0C    /* PCI Standard Hot-Plug Controller */
 #define  PCI_CAP_ID_EXP        0x10    /* PCI Express */
index b44e01a70914a81cccabfdbc4ad4c4df1e3a5afc..6cd91e3f982052df783c2ec9b9df130bff118659 100644 (file)
@@ -62,6 +62,12 @@ struct pcie_port_service_driver {
        int (*suspend) (struct pcie_device *dev, pm_message_t state);
        int (*resume) (struct pcie_device *dev);
 
+       /* Service Error Recovery Handler */
+       struct pci_error_handlers *err_handler;
+
+       /* Link Reset Capability - AER service driver specific */
+       pci_ers_result_t (*reset_link) (struct pci_dev *dev);
+
        const struct pcie_port_service_id *id_table;
        struct device_driver driver;
 };
index 29960b03bef75ef031054485c6df960aab0bdc50..93da7e2d9f30bdda2268d8163e3c9f29d73a4a4a 100644 (file)
@@ -76,6 +76,8 @@ extern int FASTCALL(attach_pid(struct task_struct *task,
                                enum pid_type type, int nr));
 
 extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
+extern void FASTCALL(transfer_pid(struct task_struct *old,
+                                 struct task_struct *new, enum pid_type));
 
 /*
  * look up a PID in the hash table. Must be called with the tasklist_lock
index 782090c689322bec205fc7fb969f3ed23a2fd89c..29cd6dee13db968266e14dcefee386eaf421fdeb 100644 (file)
@@ -49,6 +49,8 @@ struct platform_driver {
        int (*remove)(struct platform_device *);
        void (*shutdown)(struct platform_device *);
        int (*suspend)(struct platform_device *, pm_message_t state);
+       int (*suspend_late)(struct platform_device *, pm_message_t state);
+       int (*resume_early)(struct platform_device *);
        int (*resume)(struct platform_device *);
        struct device_driver driver;
 };
index 658c1b93d5bb22d4e8efbe30d299e06a2e4ba834..6b27e07aef199531387dc65bcc400c9157c79a9d 100644 (file)
@@ -142,29 +142,61 @@ typedef struct pm_message {
 } pm_message_t;
 
 /*
- * There are 4 important states driver can be in:
- * ON     -- driver is working
- * FREEZE -- stop operations and apply whatever policy is applicable to a
- *           suspended driver of that class, freeze queues for block like IDE
- *           does, drop packets for ethernet, etc... stop DMA engine too etc...
- *           so a consistent image can be saved; but do not power any hardware
- *           down.
- * SUSPEND - like FREEZE, but hardware is doing as much powersaving as
- *           possible. Roughly pci D3.
+ * Several driver power state transitions are externally visible, affecting
+ * the state of pending I/O queues and (for drivers that touch hardware)
+ * interrupts, wakeups, DMA, and other hardware state.  There may also be
+ * internal transitions to various low power modes, which are transparent
+ * to the rest of the driver stack (such as a driver that's ON gating off
+ * clocks which are not in active use).
  *
- * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3
- * (SUSPEND).  We'll need to fix the drivers. So yes, putting 3 to all different
- * defines is intentional, and will go away as soon as drivers are fixed.  Also
- * note that typedef is neccessary, we'll probably want to switch to
- *   typedef struct pm_message_t { int event; int flags; } pm_message_t
- * or something similar soon.
+ * One transition is triggered by resume(), after a suspend() call; the
+ * message is implicit:
+ *
+ * ON          Driver starts working again, responding to hardware events
+ *             and software requests.  The hardware may have gone through
+ *             a power-off reset, or it may have maintained state from the
+ *             previous suspend() which the driver will rely on while
+ *             resuming.  On most platforms, there are no restrictions on
+ *             availability of resources like clocks during resume().
+ *
+ * Other transitions are triggered by messages sent using suspend().  All
+ * these transitions quiesce the driver, so that I/O queues are inactive.
+ * That commonly entails turning off IRQs and DMA; there may be rules
+ * about how to quiesce that are specific to the bus or the device's type.
+ * (For example, network drivers mark the link state.)  Other details may
+ * differ according to the message:
+ *
+ * SUSPEND     Quiesce, enter a low power device state appropriate for
+ *             the upcoming system state (such as PCI_D3hot), and enable
+ *             wakeup events as appropriate.
+ *
+ * FREEZE      Quiesce operations so that a consistent image can be saved;
+ *             but do NOT otherwise enter a low power device state, and do
+ *             NOT emit system wakeup events.
+ *
+ * PRETHAW     Quiesce as if for FREEZE; additionally, prepare for restoring
+ *             the system from a snapshot taken after an earlier FREEZE.
+ *             Some drivers will need to reset their hardware state instead
+ *             of preserving it, to ensure that it's never mistaken for the
+ *             state which that earlier snapshot had set up.
+ *
+ * A minimally power-aware driver treats all messages as SUSPEND, fully
+ * reinitializes its device during resume() -- whether or not it was reset
+ * during the suspend/resume cycle -- and can't issue wakeup events.
+ *
+ * More power-aware drivers may also use low power states at runtime as
+ * well as during system sleep states like PM_SUSPEND_STANDBY.  They may
+ * be able to use wakeup events to exit from runtime low-power states,
+ * or from system low-power states such as standby or suspend-to-RAM.
  */
 
 #define PM_EVENT_ON 0
 #define PM_EVENT_FREEZE 1
 #define PM_EVENT_SUSPEND 2
+#define PM_EVENT_PRETHAW 3
 
 #define PMSG_FREEZE    ((struct pm_message){ .event = PM_EVENT_FREEZE, })
+#define PMSG_PRETHAW   ((struct pm_message){ .event = PM_EVENT_PRETHAW, })
 #define PMSG_SUSPEND   ((struct pm_message){ .event = PM_EVENT_SUSPEND, })
 #define PMSG_ON                ((struct pm_message){ .event = PM_EVENT_ON, })
 
@@ -190,6 +222,7 @@ extern void device_resume(void);
 extern suspend_disk_method_t pm_disk_mode;
 
 extern int device_suspend(pm_message_t state);
+extern int device_prepare_suspend(pm_message_t state);
 
 #define device_set_wakeup_enable(dev,val) \
        ((dev)->power.should_wakeup = !!(val))
index 3435ca38dd142ee705bc57032d0fd855b8c18635..57f70bc8b24bba1bf3f9e9336a1a10b01945778c 100644 (file)
@@ -268,7 +268,9 @@ static inline struct proc_dir_entry *PDE(const struct inode *inode)
 struct proc_maps_private {
        struct pid *pid;
        struct task_struct *task;
+#ifdef CONFIG_MMU
        struct vm_area_struct *tail_vma;
+#endif
 };
 
 #endif /* _LINUX_PROC_FS_H */
index 34ed0d99b1bd1ccde1dee28a164bfded8fb1fc37..9d4aa7f95bc8a9172b021f5d1c5137290f51c336 100644 (file)
@@ -819,6 +819,11 @@ struct task_struct {
        unsigned did_exec:1;
        pid_t pid;
        pid_t tgid;
+
+#ifdef CONFIG_CC_STACKPROTECTOR
+       /* Canary value for the -fstack-protector gcc feature */
+       unsigned long stack_canary;
+#endif
        /* 
         * pointers to (original) parent process, youngest child, younger sibling,
         * older sibling, respectively.  (p->father can be replaced with 
@@ -865,6 +870,15 @@ struct task_struct {
        struct key *thread_keyring;     /* keyring private to this thread */
        unsigned char jit_keyring;      /* default keyring to attach requested keys to */
 #endif
+       /*
+        * fpu_counter contains the number of consecutive context switches
+        * that the FPU is used. If this is over a threshold, the lazy fpu
+        * saving becomes unlazy to save the trap. This is an unsigned char
+        * so that after 256 times the counter wraps and the behavior turns
+        * lazy again; this to deal with bursty apps that only use FPU for
+        * a short time
+        */
+       unsigned char fpu_counter;
        int oomkilladj; /* OOM kill score adjustment (bit shift). */
        char comm[TASK_COMM_LEN]; /* executable name excluding path
                                     - access with [gs]et_task_comm (which lock
index 66d6eb78d1c64e1f59691e37ae561f4c670d969b..a96fd9310d55a7dc89176db3cdb4bc7c1ba26950 100644 (file)
@@ -60,7 +60,7 @@ extern void __init kmem_cache_init(void);
 extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long,
                                       void (*)(void *, kmem_cache_t *, unsigned long),
                                       void (*)(void *, kmem_cache_t *, unsigned long));
-extern int kmem_cache_destroy(kmem_cache_t *);
+extern void kmem_cache_destroy(kmem_cache_t *);
 extern int kmem_cache_shrink(kmem_cache_t *);
 extern void *kmem_cache_alloc(kmem_cache_t *, gfp_t);
 extern void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
@@ -249,7 +249,7 @@ struct kmem_cache *kmem_cache_create(const char *c, size_t, size_t,
        unsigned long,
        void (*)(void *, struct kmem_cache *, unsigned long),
        void (*)(void *, struct kmem_cache *, unsigned long));
-int kmem_cache_destroy(struct kmem_cache *c);
+void kmem_cache_destroy(struct kmem_cache *c);
 void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags);
 void *kmem_cache_zalloc(struct kmem_cache *, gfp_t);
 void kmem_cache_free(struct kmem_cache *c, void *b);
index 6df3b1501559aadda5c5c926bc836431a1e0565a..f098dff93f6bc26cd732d15b75a9ff69d894d42e 100644 (file)
@@ -89,7 +89,6 @@ struct smb_fattr {
        struct timespec f_atime;
        struct timespec f_mtime;
        struct timespec f_ctime;
-       unsigned long   f_blksize;
        unsigned long   f_blocks;
        int             f_unix;
 };
index 9cc81e5722245e6d99bf09f56b0b43ce8895837b..50e2b01e517cc3c9bdf3af4b328c4afb8d3aab21 100644 (file)
@@ -5,15 +5,16 @@
 struct stack_trace {
        unsigned int nr_entries, max_entries;
        unsigned long *entries;
+       int skip;       /* input argument: How many entries to skip */
+       int all_contexts; /* input argument: if true do than one stack */
 };
 
 extern void save_stack_trace(struct stack_trace *trace,
-                            struct task_struct *task, int all_contexts,
-                            unsigned int skip);
+                            struct task_struct *task);
 
 extern void print_stack_trace(struct stack_trace *trace, int spaces);
 #else
-# define save_stack_trace(trace, task, all, skip)      do { } while (0)
+# define save_stack_trace(trace, task)                 do { } while (0)
 # define print_stack_trace(trace)                      do { } while (0)
 #endif
 
index 008f04c5673715b33a52536e2bd4375bc064ff92..3f0f716225ecd714d1c21fac4076e6ef6fbbce12 100644 (file)
@@ -53,6 +53,7 @@ struct mq_attr;
 struct compat_stat;
 struct compat_timeval;
 struct robust_list_head;
+struct getcpu_cache;
 
 #include <linux/types.h>
 #include <linux/aio_abi.h>
@@ -596,5 +597,6 @@ asmlinkage long sys_get_robust_list(int pid,
                                    size_t __user *len_ptr);
 asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
                                    size_t len);
+asmlinkage long sys_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *cache);
 
 #endif
index eca555781d05e1d67e62d070202ced6ac6bcfb84..1b24bd45e0804675646b5628cace0fbed1901ab0 100644 (file)
@@ -150,6 +150,8 @@ enum
        KERN_IA64_UNALIGNED=72, /* int: ia64 unaligned userland trap enable */
        KERN_COMPAT_LOG=73,     /* int: print compat layer  messages */
        KERN_MAX_LOCK_DEPTH=74,
+       KERN_NMI_WATCHDOG=75, /* int: enable/disable nmi watchdog */
+       KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */
 };
 
 
index 1ea5d3cda6ae2374056769173d6bd56fa9fd4128..6d5c43d31dec27e7b0a0131c5cc1c03a5b030612 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef _SYSFS_H_
 #define _SYSFS_H_
 
+#include <linux/compiler.h>
 #include <asm/atomic.h>
 
 struct kobject;
@@ -86,40 +87,44 @@ struct sysfs_dirent {
 
 #ifdef CONFIG_SYSFS
 
-extern int
+extern int __must_check
 sysfs_create_dir(struct kobject *);
 
 extern void
 sysfs_remove_dir(struct kobject *);
 
-extern int
+extern int __must_check
 sysfs_rename_dir(struct kobject *, const char *new_name);
 
-extern int
+extern int __must_check
 sysfs_create_file(struct kobject *, const struct attribute *);
 
-extern int
+extern int __must_check
 sysfs_update_file(struct kobject *, const struct attribute *);
 
-extern int
+extern int __must_check
 sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode);
 
 extern void
 sysfs_remove_file(struct kobject *, const struct attribute *);
 
-extern int
+extern int __must_check
 sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name);
 
 extern void
 sysfs_remove_link(struct kobject *, const char * name);
 
-int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);
-int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
+int __must_check sysfs_create_bin_file(struct kobject *kobj,
+                                       struct bin_attribute *attr);
+void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr);
 
-int sysfs_create_group(struct kobject *, const struct attribute_group *);
+int __must_check sysfs_create_group(struct kobject *,
+                                       const struct attribute_group *);
 void sysfs_remove_group(struct kobject *, const struct attribute_group *);
 void sysfs_notify(struct kobject * k, char *dir, char *attr);
 
+extern int __must_check sysfs_init(void);
+
 #else /* CONFIG_SYSFS */
 
 static inline int sysfs_create_dir(struct kobject * k)
@@ -191,6 +196,11 @@ static inline void sysfs_notify(struct kobject * k, char *dir, char *attr)
 {
 }
 
+static inline int __must_check sysfs_init(void)
+{
+       return 0;
+}
+
 #endif /* CONFIG_SYSFS */
 
 #endif /* _SYSFS_H_ */
index 391e7ed1eb3fc05ea2eeb8548e42381c8aefa7e5..a48d7f11c7be06772327604dc40c3f91b0b57145 100644 (file)
@@ -19,4 +19,26 @@ static inline unsigned long __copy_from_user_nocache(void *to,
 
 #endif         /* ARCH_HAS_NOCACHE_UACCESS */
 
+/**
+ * probe_kernel_address(): safely attempt to read from a location
+ * @addr: address to read from - its type is type typeof(retval)*
+ * @retval: read into this variable
+ *
+ * Safely read from address @addr into variable @revtal.  If a kernel fault
+ * happens, handle that and return -EFAULT.
+ * We ensure that the __get_user() is executed in atomic context so that
+ * do_page_fault() doesn't attempt to take mmap_sem.  This makes
+ * probe_kernel_address() suitable for use within regions where the caller
+ * already holds mmap_sem, or other locks which nest inside mmap_sem.
+ */
+#define probe_kernel_address(addr, retval)             \
+       ({                                              \
+               long ret;                               \
+                                                       \
+               inc_preempt_count();                    \
+               ret = __get_user(retval, addr);         \
+               dec_preempt_count();                    \
+               ret;                                    \
+       })
+
 #endif         /* __LINUX_UACCESS_H__ */
index d2bd0c8e015408c0152fe7b9927ec2d5deda5100..0da15b0b02becfc3db29b62afc5cd6270140ed18 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/fs.h>          /* for struct file_operations */
 #include <linux/completion.h>  /* for struct completion */
 #include <linux/sched.h>       /* for current && schedule_timeout */
+#include <linux/mutex.h>       /* for struct mutex */
 
 struct usb_device;
 struct usb_driver;
@@ -102,8 +103,13 @@ enum usb_interface_condition {
  *     number from the USB core by calling usb_register_dev().
  * @condition: binding state of the interface: not bound, binding
  *     (in probe()), bound to a driver, or unbinding (in disconnect())
+ * @is_active: flag set when the interface is bound and not suspended.
+ * @needs_remote_wakeup: flag set when the driver requires remote-wakeup
+ *     capability during autosuspend.
  * @dev: driver model's view of this device
  * @class_dev: driver model's class view of this device.
+ * @pm_usage_cnt: PM usage counter for this interface; autosuspend is not
+ *     allowed unless the counter is 0.
  *
  * USB device drivers attach to interfaces on a physical device.  Each
  * interface encapsulates a single high level function, such as feeding
@@ -142,8 +148,12 @@ struct usb_interface {
        int minor;                      /* minor number this interface is
                                         * bound to */
        enum usb_interface_condition condition;         /* state of binding */
+       unsigned is_active:1;           /* the interface is not suspended */
+       unsigned needs_remote_wakeup:1; /* driver requires remote wakeup */
+
        struct device dev;              /* interface specific device info */
        struct class_device *class_dev;
+       int pm_usage_cnt;               /* usage counter for autosuspend */
 };
 #define        to_usb_interface(d) container_of(d, struct usb_interface, dev)
 #define        interface_to_usbdev(intf) \
@@ -254,8 +264,6 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
 
 /* ----------------------------------------------------------------------- */
 
-struct usb_operations;
-
 /* USB device number allocation bitmap */
 struct usb_devmap {
        unsigned long devicemap[128 / (8*sizeof(unsigned long))];
@@ -268,6 +276,7 @@ struct usb_bus {
        struct device *controller;      /* host/master side hardware */
        int busnum;                     /* Bus number (in order of reg) */
        char *bus_name;                 /* stable id (PCI slot_name etc) */
+       u8 uses_dma;                    /* Does the host controller use DMA? */
        u8 otg_port;                    /* 0, or number of OTG/HNP port */
        unsigned is_b_host:1;           /* true during some HNP roleswitches */
        unsigned b_hnp_enable:1;        /* OTG: did A-Host enable HNP? */
@@ -276,10 +285,8 @@ struct usb_bus {
                                         * round-robin allocation */
 
        struct usb_devmap devmap;       /* device address allocation map */
-       struct usb_operations *op;      /* Operations (specific to the HC) */
        struct usb_device *root_hub;    /* Root hub */
        struct list_head bus_list;      /* list of busses */
-       void *hcpriv;                   /* Host Controller private data */
 
        int bandwidth_allocated;        /* on this bus: how much of the time
                                         * reserved for periodic (intr/iso)
@@ -294,8 +301,6 @@ struct usb_bus {
        struct dentry *usbfs_dentry;    /* usbfs dentry entry for the bus */
 
        struct class_device *class_dev; /* class device for this bus */
-       struct kref kref;               /* reference counting for this bus */
-       void (*release)(struct usb_bus *bus);
 
 #if defined(CONFIG_USB_MON)
        struct mon_bus *mon_bus;        /* non-null when associated */
@@ -350,6 +355,7 @@ struct usb_device {
 
        unsigned short bus_mA;          /* Current available from the bus */
        u8 portnum;                     /* Parent port number (origin 1) */
+       u8 level;                       /* Number of USB hub ancestors */
 
        int have_langid;                /* whether string_langid is valid */
        int string_langid;              /* language ID for strings */
@@ -373,6 +379,15 @@ struct usb_device {
 
        int maxchild;                   /* Number of ports if hub */
        struct usb_device *children[USB_MAXCHILDREN];
+
+#ifdef CONFIG_PM
+       struct work_struct autosuspend; /* for delayed autosuspends */
+       struct mutex pm_mutex;          /* protects PM operations */
+       int pm_usage_cnt;               /* usage counter for autosuspend */
+
+       unsigned auto_pm:1;             /* autosuspend/resume in progress */
+       unsigned do_remote_wakeup:1;    /* remote wakeup should be enabled */
+#endif
 };
 #define        to_usb_device(d) container_of(d, struct usb_device, dev)
 
@@ -384,7 +399,7 @@ extern void usb_put_dev(struct usb_device *dev);
 #define usb_unlock_device(udev)                up(&(udev)->dev.sem)
 #define usb_trylock_device(udev)       down_trylock(&(udev)->dev.sem)
 extern int usb_lock_device_for_reset(struct usb_device *udev,
-               struct usb_interface *iface);
+                                    const struct usb_interface *iface);
 
 /* USB port reset for device reinitialization */
 extern int usb_reset_device(struct usb_device *dev);
@@ -393,6 +408,17 @@ extern int usb_reset_composite_device(struct usb_device *dev,
 
 extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
 
+/* USB autosuspend and autoresume */
+#ifdef CONFIG_USB_SUSPEND
+extern int usb_autopm_get_interface(struct usb_interface *intf);
+extern void usb_autopm_put_interface(struct usb_interface *intf);
+
+#else
+#define usb_autopm_get_interface(intf)         0
+#define usb_autopm_put_interface(intf)         do {} while (0)
+#endif
+
+
 /*-------------------------------------------------------------------------*/
 
 /* for drivers using iso endpoints */
@@ -423,10 +449,10 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
 
 extern struct usb_interface *usb_find_interface(struct usb_driver *drv,
                int minor);
-extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev,
+extern struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
                unsigned ifnum);
 extern struct usb_host_interface *usb_altnum_to_altsetting(
-               struct usb_interface *intf, unsigned int altnum);
+               const struct usb_interface *intf, unsigned int altnum);
 
 
 /**
@@ -464,6 +490,20 @@ static inline int usb_make_path (struct usb_device *dev, char *buf,
 
 /*-------------------------------------------------------------------------*/
 
+extern int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd);
+extern int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd);
+
+/*-------------------------------------------------------------------------*/
+
 #define USB_DEVICE_ID_MATCH_DEVICE \
                (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT)
 #define USB_DEVICE_ID_MATCH_DEV_RANGE \
@@ -540,7 +580,17 @@ struct usb_dynids {
 };
 
 /**
- * struct usb_driver - identifies USB driver to usbcore
+ * struct usbdrv_wrap - wrapper for driver-model structure
+ * @driver: The driver-model core driver structure.
+ * @for_devices: Non-zero for device drivers, 0 for interface drivers.
+ */
+struct usbdrv_wrap {
+       struct device_driver driver;
+       int for_devices;
+};
+
+/**
+ * struct usb_driver - identifies USB interface driver to usbcore
  * @name: The driver name should be unique among USB drivers,
  *     and should normally be the same as the module name.
  * @probe: Called to see if the driver is willing to manage a particular
@@ -567,12 +617,14 @@ struct usb_dynids {
  *     or your driver's probe function will never get called.
  * @dynids: used internally to hold the list of dynamically added device
  *     ids for this driver.
- * @driver: the driver model core driver structure.
+ * @drvwrap: Driver-model core structure wrapper.
  * @no_dynamic_id: if set to 1, the USB core will not allow dynamic ids to be
  *     added to this driver by preventing the sysfs file from being created.
+ * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
+ *     for interfaces bound to this driver.
  *
- * USB drivers must provide a name, probe() and disconnect() methods,
- * and an id_table.  Other driver fields are optional.
+ * USB interface drivers must provide a name, probe() and disconnect()
+ * methods, and an id_table.  Other driver fields are optional.
  *
  * The id_table is used in hotplugging.  It holds a set of descriptors,
  * and specialized data may be associated with each entry.  That table
@@ -606,10 +658,44 @@ struct usb_driver {
        const struct usb_device_id *id_table;
 
        struct usb_dynids dynids;
-       struct device_driver driver;
+       struct usbdrv_wrap drvwrap;
        unsigned int no_dynamic_id:1;
+       unsigned int supports_autosuspend:1;
 };
-#define        to_usb_driver(d) container_of(d, struct usb_driver, driver)
+#define        to_usb_driver(d) container_of(d, struct usb_driver, drvwrap.driver)
+
+/**
+ * struct usb_device_driver - identifies USB device driver to usbcore
+ * @name: The driver name should be unique among USB drivers,
+ *     and should normally be the same as the module name.
+ * @probe: Called to see if the driver is willing to manage a particular
+ *     device.  If it is, probe returns zero and uses dev_set_drvdata()
+ *     to associate driver-specific data with the device.  If unwilling
+ *     to manage the device, return a negative errno value.
+ * @disconnect: Called when the device is no longer accessible, usually
+ *     because it has been (or is being) disconnected or the driver's
+ *     module is being unloaded.
+ * @suspend: Called when the device is going to be suspended by the system.
+ * @resume: Called when the device is being resumed by the system.
+ * @drvwrap: Driver-model core structure wrapper.
+ * @supports_autosuspend: if set to 0, the USB core will not allow autosuspend
+ *     for devices bound to this driver.
+ *
+ * USB drivers must provide all the fields listed above except drvwrap.
+ */
+struct usb_device_driver {
+       const char *name;
+
+       int (*probe) (struct usb_device *udev);
+       void (*disconnect) (struct usb_device *udev);
+
+       int (*suspend) (struct usb_device *udev, pm_message_t message);
+       int (*resume) (struct usb_device *udev);
+       struct usbdrv_wrap drvwrap;
+       unsigned int supports_autosuspend:1;
+};
+#define        to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
+               drvwrap.driver)
 
 extern struct bus_type usb_bus_type;
 
@@ -633,13 +719,17 @@ struct usb_class_driver {
  * use these in module_init()/module_exit()
  * and don't forget MODULE_DEVICE_TABLE(usb, ...)
  */
-int usb_register_driver(struct usb_driver *, struct module *);
+extern int usb_register_driver(struct usb_driver *, struct module *);
 static inline int usb_register(struct usb_driver *driver)
 {
        return usb_register_driver(driver, THIS_MODULE);
 }
 extern void usb_deregister(struct usb_driver *);
 
+extern int usb_register_device_driver(struct usb_device_driver *,
+                       struct module *);
+extern void usb_deregister_device_driver(struct usb_device_driver *);
+
 extern int usb_register_dev(struct usb_interface *intf,
                            struct usb_class_driver *class_driver);
 extern void usb_deregister_dev(struct usb_interface *intf,
@@ -885,7 +975,7 @@ struct urb
  * @setup_packet: pointer to the setup_packet buffer
  * @transfer_buffer: pointer to the transfer buffer
  * @buffer_length: length of the transfer buffer
- * @complete: pointer to the usb_complete_t function
+ * @complete_fn: pointer to the usb_complete_t function
  * @context: what to set the urb context to.
  *
  * Initializes a control urb with the proper information needed to submit
@@ -897,7 +987,7 @@ static inline void usb_fill_control_urb (struct urb *urb,
                                         unsigned char *setup_packet,
                                         void *transfer_buffer,
                                         int buffer_length,
-                                        usb_complete_t complete,
+                                        usb_complete_t complete_fn,
                                         void *context)
 {
        spin_lock_init(&urb->lock);
@@ -906,7 +996,7 @@ static inline void usb_fill_control_urb (struct urb *urb,
        urb->setup_packet = setup_packet;
        urb->transfer_buffer = transfer_buffer;
        urb->transfer_buffer_length = buffer_length;
-       urb->complete = complete;
+       urb->complete = complete_fn;
        urb->context = context;
 }
 
@@ -917,7 +1007,7 @@ static inline void usb_fill_control_urb (struct urb *urb,
  * @pipe: the endpoint pipe
  * @transfer_buffer: pointer to the transfer buffer
  * @buffer_length: length of the transfer buffer
- * @complete: pointer to the usb_complete_t function
+ * @complete_fn: pointer to the usb_complete_t function
  * @context: what to set the urb context to.
  *
  * Initializes a bulk urb with the proper information needed to submit it
@@ -928,7 +1018,7 @@ static inline void usb_fill_bulk_urb (struct urb *urb,
                                      unsigned int pipe,
                                      void *transfer_buffer,
                                      int buffer_length,
-                                     usb_complete_t complete,
+                                     usb_complete_t complete_fn,
                                      void *context)
 {
        spin_lock_init(&urb->lock);
@@ -936,7 +1026,7 @@ static inline void usb_fill_bulk_urb (struct urb *urb,
        urb->pipe = pipe;
        urb->transfer_buffer = transfer_buffer;
        urb->transfer_buffer_length = buffer_length;
-       urb->complete = complete;
+       urb->complete = complete_fn;
        urb->context = context;
 }
 
@@ -947,7 +1037,7 @@ static inline void usb_fill_bulk_urb (struct urb *urb,
  * @pipe: the endpoint pipe
  * @transfer_buffer: pointer to the transfer buffer
  * @buffer_length: length of the transfer buffer
- * @complete: pointer to the usb_complete_t function
+ * @complete_fn: pointer to the usb_complete_t function
  * @context: what to set the urb context to.
  * @interval: what to set the urb interval to, encoded like
  *     the endpoint descriptor's bInterval value.
@@ -963,7 +1053,7 @@ static inline void usb_fill_int_urb (struct urb *urb,
                                     unsigned int pipe,
                                     void *transfer_buffer,
                                     int buffer_length,
-                                    usb_complete_t complete,
+                                    usb_complete_t complete_fn,
                                     void *context,
                                     int interval)
 {
@@ -972,7 +1062,7 @@ static inline void usb_fill_int_urb (struct urb *urb,
        urb->pipe = pipe;
        urb->transfer_buffer = transfer_buffer;
        urb->transfer_buffer_length = buffer_length;
-       urb->complete = complete;
+       urb->complete = complete_fn;
        urb->context = context;
        if (dev->speed == USB_SPEED_HIGH)
                urb->interval = 1 << (interval - 1);
@@ -990,7 +1080,6 @@ extern int usb_submit_urb(struct urb *urb, gfp_t mem_flags);
 extern int usb_unlink_urb(struct urb *urb);
 extern void usb_kill_urb(struct urb *urb);
 
-#define HAVE_USB_BUFFERS
 void *usb_buffer_alloc (struct usb_device *dev, size_t size,
        gfp_t mem_flags, dma_addr_t *dma);
 void usb_buffer_free (struct usb_device *dev, size_t size,
@@ -1003,14 +1092,14 @@ void usb_buffer_unmap (struct urb *urb);
 #endif
 
 struct scatterlist;
-int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int nents);
+int usb_buffer_map_sg(const struct usb_device *dev, unsigned pipe,
+                     struct scatterlist *sg, int nents);
 #if 0
-void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int n_hw_ents);
+void usb_buffer_dmasync_sg(const struct usb_device *dev, unsigned pipe,
+                          struct scatterlist *sg, int n_hw_ents);
 #endif
-void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
-               struct scatterlist *sg, int n_hw_ents);
+void usb_buffer_unmap_sg(const struct usb_device *dev, unsigned pipe,
+                        struct scatterlist *sg, int n_hw_ents);
 
 /*-------------------------------------------------------------------*
  *                         SYNCHRONOUS CALL SUPPORT                  *
@@ -1038,6 +1127,9 @@ extern int usb_clear_halt(struct usb_device *dev, int pipe);
 extern int usb_reset_configuration(struct usb_device *dev);
 extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
 
+/* this request isn't really synchronous, but it belongs with the others */
+extern int usb_driver_set_configuration(struct usb_device *udev, int config);
+
 /*
  * timeouts, in milliseconds, used for sending/receiving control messages
  * they typically complete within a few frames (msec) after they're issued
diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h
new file mode 100644 (file)
index 0000000..6bd2359
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * <linux/usb/audio.h> -- USB Audio definitions.
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This file holds USB constants and structures defined
+ * by the USB Device Class Definition for Audio Devices.
+ * Comments below reference relevant sections of that document:
+ *
+ * http://www.usb.org/developers/devclass_docs/audio10.pdf
+ */
+
+#ifndef __LINUX_USB_AUDIO_H
+#define __LINUX_USB_AUDIO_H
+
+#include <linux/types.h>
+
+/* A.2 Audio Interface Subclass Codes */
+#define USB_SUBCLASS_AUDIOCONTROL      0x01
+#define USB_SUBCLASS_AUDIOSTREAMING    0x02
+#define USB_SUBCLASS_MIDISTREAMING     0x03
+
+/* 4.3.2  Class-Specific AC Interface Descriptor */
+struct usb_ac_header_descriptor {
+       __u8  bLength;                  // 8+n
+       __u8  bDescriptorType;          // USB_DT_CS_INTERFACE
+       __u8  bDescriptorSubtype;       // USB_MS_HEADER
+       __le16 bcdADC;                  // 0x0100
+       __le16 wTotalLength;            // includes Unit and Terminal desc.
+       __u8  bInCollection;            // n
+       __u8  baInterfaceNr[];          // [n]
+} __attribute__ ((packed));
+
+#define USB_DT_AC_HEADER_SIZE(n)       (8+(n))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_USB_AC_HEADER_DESCRIPTOR(n)                    \
+struct usb_ac_header_descriptor_##n {                          \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __le16 bcdADC;                                          \
+       __le16 wTotalLength;                                    \
+       __u8  bInCollection;                                    \
+       __u8  baInterfaceNr[n];                                 \
+} __attribute__ ((packed))
+
+#endif
diff --git a/include/linux/usb/midi.h b/include/linux/usb/midi.h
new file mode 100644 (file)
index 0000000..11a97d5
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * <linux/usb/midi.h> -- USB MIDI definitions.
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This file holds USB constants and structures defined
+ * by the USB Device Class Definition for MIDI Devices.
+ * Comments below reference relevant sections of that document:
+ *
+ * http://www.usb.org/developers/devclass_docs/midi10.pdf
+ */
+
+#ifndef __LINUX_USB_MIDI_H
+#define __LINUX_USB_MIDI_H
+
+#include <linux/types.h>
+
+/* A.1  MS Class-Specific Interface Descriptor Subtypes */
+#define USB_MS_HEADER          0x01
+#define USB_MS_MIDI_IN_JACK    0x02
+#define USB_MS_MIDI_OUT_JACK   0x03
+#define USB_MS_ELEMENT         0x04
+
+/* A.2  MS Class-Specific Endpoint Descriptor Subtypes */
+#define USB_MS_GENERAL         0x01
+
+/* A.3  MS MIDI IN and OUT Jack Types */
+#define USB_MS_EMBEDDED                0x01
+#define USB_MS_EXTERNAL                0x02
+
+/* 6.1.2.1  Class-Specific MS Interface Header Descriptor */
+struct usb_ms_header_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubtype;
+       __le16 bcdMSC;
+       __le16 wTotalLength;
+} __attribute__ ((packed));
+
+#define USB_DT_MS_HEADER_SIZE  7
+
+/* 6.1.2.2  MIDI IN Jack Descriptor */
+struct usb_midi_in_jack_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;          // USB_DT_CS_INTERFACE
+       __u8  bDescriptorSubtype;       // USB_MS_MIDI_IN_JACK
+       __u8  bJackType;                // USB_MS_EMBEDDED/EXTERNAL
+       __u8  bJackID;
+       __u8  iJack;
+} __attribute__ ((packed));
+
+#define USB_DT_MIDI_IN_SIZE    6
+
+struct usb_midi_source_pin {
+       __u8  baSourceID;
+       __u8  baSourcePin;
+} __attribute__ ((packed));
+
+/* 6.1.2.3  MIDI OUT Jack Descriptor */
+struct usb_midi_out_jack_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;          // USB_DT_CS_INTERFACE
+       __u8  bDescriptorSubtype;       // USB_MS_MIDI_OUT_JACK
+       __u8  bJackType;                // USB_MS_EMBEDDED/EXTERNAL
+       __u8  bJackID;
+       __u8  bNrInputPins;             // p
+       struct usb_midi_source_pin pins[]; // [p]
+       /*__u8  iJack;  -- ommitted due to variable-sized pins[] */
+} __attribute__ ((packed));
+
+#define USB_DT_MIDI_OUT_SIZE(p)        (7 + 2 * (p))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(p)                        \
+struct usb_midi_out_jack_descriptor_##p {                      \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __u8  bJackType;                                        \
+       __u8  bJackID;                                          \
+       __u8  bNrInputPins;                                     \
+       struct usb_midi_source_pin pins[p];                     \
+       __u8  iJack;                                            \
+} __attribute__ ((packed))
+
+/* 6.2.2  Class-Specific MS Bulk Data Endpoint Descriptor */
+struct usb_ms_endpoint_descriptor {
+       __u8  bLength;                  // 4+n
+       __u8  bDescriptorType;          // USB_DT_CS_ENDPOINT
+       __u8  bDescriptorSubtype;       // USB_MS_GENERAL
+       __u8  bNumEmbMIDIJack;          // n
+       __u8  baAssocJackID[];          // [n]
+} __attribute__ ((packed));
+
+#define USB_DT_MS_ENDPOINT_SIZE(n)     (4 + (n))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(n)                  \
+struct usb_ms_endpoint_descriptor_##n {                                \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __u8  bNumEmbMIDIJack;                                  \
+       __u8  baAssocJackID[n];                                 \
+} __attribute__ ((packed))
+
+#endif
similarity index 97%
rename from include/linux/usb_otg.h
rename to include/linux/usb/otg.h
index f827f6e203c219249b39cd41929a44aae6aa77e9..9897f7a818c561fb6a6a04e2004874ee8ca4d967 100644 (file)
@@ -1,4 +1,4 @@
-// include/linux/usb_otg.h 
+// include/linux/usb/otg.h
 
 /*
  * These APIs may be used between USB controllers.  USB device drivers
@@ -52,7 +52,7 @@ struct otg_transceiver {
        u16                     port_change;
 
        /* bind/unbind the host controller */
-       int     (*set_host)(struct otg_transceiver *otg,
+       int     (*set_host)(struct otg_transceiver *otg,
                                struct usb_bus *host);
 
        /* bind/unbind the peripheral controller */
index e7fc5fed5b98b8044d940fa4a7ded769a09a0452..2ae76fe52ff75e483806cd48c2f3e29fadfd89ac 100644 (file)
@@ -108,6 +108,9 @@ enum { US_DO_ALL_FLAGS };
 #ifdef CONFIG_USB_STORAGE_ALAUDA
 #define US_PR_ALAUDA    0xf4           /* Alauda chipsets */
 #endif
+#ifdef CONFIG_USB_STORAGE_KARMA
+#define US_PR_KARMA     0xf5           /* Rio Karma */
+#endif
 
 #define US_PR_DEVICE   0xff            /* Use device's value */
 
index 46919f9f5eb35b9d023e9c5a7818bc528b5fa2e5..4d0909e53595dcd9423c9e845bd13d0da36bfcaa 100644 (file)
@@ -24,5 +24,5 @@
 #define VERMAGIC_STRING                                                \
        UTS_RELEASE " "                                                 \
        MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT                     \
-       MODULE_VERMAGIC_MODULE_UNLOAD MODULE_ARCH_VERMAGIC              \
-       "gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__)
+       MODULE_VERMAGIC_MODULE_UNLOAD MODULE_ARCH_VERMAGIC
+
index dee88c6b6fa74e907957e112d2c06f47eb6773a3..ce5f1482e6be4fe2e90589be3822bfeb9da4242e 100644 (file)
@@ -62,7 +62,6 @@ extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
 extern struct vm_struct *get_vm_area_node(unsigned long size,
                                        unsigned long flags, int node);
 extern struct vm_struct *remove_vm_area(void *addr);
-extern struct vm_struct *__remove_vm_area(void *addr);
 extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
                        struct page ***pages);
 extern void unmap_vm_area(struct vm_struct *area);
index 13588564b42b04331a107c45fb97a7a9337987b8..a50a0130fd9eb020a6ef8c01f416244fd03e1c19 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file define a set of standard wireless extensions
  *
- * Version :   20      17.2.06
+ * Version :   21      14.3.06
  *
  * Authors :   Jean Tourrilhes - HPL - <jt@hpl.hp.com>
  * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
 
 /***************************** INCLUDES *****************************/
 
+/* This header is used in user-space, therefore need to be sanitised
+ * for that purpose. Those includes are usually not compatible with glibc.
+ * To know which includes to use in user-space, check iwlib.h. */
+#ifdef __KERNEL__
 #include <linux/types.h>               /* for "caddr_t" et al          */
 #include <linux/socket.h>              /* for "struct sockaddr" et al  */
 #include <linux/if.h>                  /* for IFNAMSIZ and co... */
+#endif /* __KERNEL__ */
 
 /***************************** VERSION *****************************/
 /*
@@ -80,7 +85,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT   20
+#define WIRELESS_EXT   21
 
 /*
  * Changes :
  * V19 to V20
  * ----------
  *     - RtNetlink requests support (SET/GET)
+ *
+ * V20 to V21
+ * ----------
+ *     - Remove (struct net_device *)->get_wireless_stats()
+ *     - Change length in ESSID and NICK to strlen() instead of strlen()+1
+ *     - Add IW_RETRY_SHORT/IW_RETRY_LONG retry modifiers
+ *     - Power/Retry relative values no longer * 100000
+ *     - Add explicit flag to tell stats are in 802.11k RCPI : IW_QUAL_RCPI
  */
 
 /**************************** CONSTANTS ****************************/
 #define IW_QUAL_QUAL_INVALID   0x10    /* Driver doesn't provide value */
 #define IW_QUAL_LEVEL_INVALID  0x20
 #define IW_QUAL_NOISE_INVALID  0x40
+#define IW_QUAL_RCPI           0x80    /* Level + Noise are 802.11k RCPI */
 #define IW_QUAL_ALL_INVALID    0x70
 
 /* Frequency flags */
 #define IW_RETRY_TYPE          0xF000  /* Type of parameter */
 #define IW_RETRY_LIMIT         0x1000  /* Maximum number of retries*/
 #define IW_RETRY_LIFETIME      0x2000  /* Maximum duration of retries in us */
-#define IW_RETRY_MODIFIER      0x000F  /* Modify a parameter */
+#define IW_RETRY_MODIFIER      0x00FF  /* Modify a parameter */
 #define IW_RETRY_MIN           0x0001  /* Value is a minimum  */
 #define IW_RETRY_MAX           0x0002  /* Value is a maximum */
 #define IW_RETRY_RELATIVE      0x0004  /* Value is not in seconds/ms/us */
+#define IW_RETRY_SHORT         0x0010  /* Value is for short packets  */
+#define IW_RETRY_LONG          0x0020  /* Value is for long packets */
 
 /* Scanning request flags */
 #define IW_SCAN_DEFAULT                0x0000  /* Default scan of the driver */
@@ -1017,7 +1033,7 @@ struct    iw_range
        /* Note : this frequency list doesn't need to fit channel numbers,
         * because each entry contain its channel index */
 
-       __u32           enc_capa; /* IW_ENC_CAPA_* bit field */
+       __u32           enc_capa;       /* IW_ENC_CAPA_* bit field */
 };
 
 /*
index 810462f8a374b63ac3096414ada7b9aff6d5732d..bb495b7f4680b112b96d82bad4a8320a29e91b11 100644 (file)
@@ -341,7 +341,7 @@ extern int video_usercopy(struct inode *inode, struct file *file,
 extern struct video_device* video_devdata(struct file*);
 
 #define to_video_device(cd) container_of(cd, struct video_device, class_dev)
-static inline int
+static inline int __must_check
 video_device_create_file(struct video_device *vfd,
                         struct class_device_attribute *attr)
 {
index 9a7656f0b5ecff5a1d83e3a547ad6aafc08dfdc5..4381006dd666aaba6f9d1e29913d65fe5c3e5a8c 100644 (file)
@@ -273,21 +273,24 @@ config UID16
          This enables the legacy 16-bit UID syscall wrappers.
 
 config SYSCTL
-       bool "Sysctl support" if EMBEDDED
-       default y
+       bool
+
+config SYSCTL_SYSCALL
+       bool "Sysctl syscall support"
+       default n
+       select SYSCTL
        ---help---
-         The sysctl interface provides a means of dynamically changing
-         certain kernel parameters and variables on the fly without requiring
-         a recompile of the kernel or reboot of the system.  The primary
-         interface consists of a system call, but if you say Y to "/proc
-         file system support", a tree of modifiable sysctl entries will be
-         generated beneath the /proc/sys directory. They are explained in the
-         files in <file:Documentation/sysctl/>.  Note that enabling this
-         option will enlarge the kernel by at least 8 KB.
-
-         As it is generally a good thing, you should say Y here unless
-         building a kernel for install/rescue disks or your system is very
-         limited in memory.
+         Enable the deprecated sysctl system call.  sys_sysctl uses
+         binary paths that have been found to be a major pain to maintain
+         and use.  The interface in /proc/sys is now the primary and what
+         everyone uses.
+
+         Nothing has been using the binary sysctl interface for some time
+         time now so nothing should break if you disable sysctl syscall
+         support, and you kernel will get marginally smaller.
+
+         Unless you have an application that uses the sys_syscall interface
+         you should probably say N here.
 
 config KALLSYMS
         bool "Load all symbols for debugging/kksymoops" if EMBEDDED
index 94aeec7aa917fbf727e5be22c55f842621b31ef3..b290aadb1d3f2a0b1448a06df90bb05f75aed42f 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/security.h>
 #include <linux/delay.h>
 #include <linux/mount.h>
+#include <linux/device.h>
 
 #include <linux/nfs_fs.h>
 #include <linux/nfs_fs_sb.h>
@@ -403,6 +404,10 @@ void __init prepare_namespace(void)
                ssleep(root_delay);
        }
 
+       /* wait for the known devices to complete their probing */
+       while (driver_probe_done() != 0)
+               msleep(100);
+
        md_run_setup();
 
        if (saved_root_name[0]) {
index 8651a720a092c4ade7e530c01b57b040c3e52539..0766e69712b2a86efa74caf3c5bd487bbbcd3753 100644 (file)
@@ -127,6 +127,18 @@ static char *ramdisk_execute_command;
 /* Setup configured maximum number of CPUs to activate */
 static unsigned int max_cpus = NR_CPUS;
 
+/*
+ * If set, this is an indication to the drivers that reset the underlying
+ * device before going ahead with the initialization otherwise driver might
+ * rely on the BIOS and skip the reset operation.
+ *
+ * This is useful if kernel is booting in an unreliable environment.
+ * For ex. kdump situaiton where previous kernel has crashed, BIOS has been
+ * skipped and devices will be in unknown state.
+ */
+unsigned int reset_devices;
+EXPORT_SYMBOL(reset_devices);
+
 /*
  * Setup routine for controlling SMP activation
  *
@@ -153,6 +165,14 @@ static int __init maxcpus(char *str)
 
 __setup("maxcpus=", maxcpus);
 
+static int __init set_reset_devices(char *str)
+{
+       reset_devices = 1;
+       return 1;
+}
+
+__setup("reset_devices", set_reset_devices);
+
 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
 static const char *panic_later, *panic_param;
@@ -162,16 +182,19 @@ extern struct obs_kernel_param __setup_start[], __setup_end[];
 static int __init obsolete_checksetup(char *line)
 {
        struct obs_kernel_param *p;
+       int had_early_param = 0;
 
        p = __setup_start;
        do {
                int n = strlen(p->str);
                if (!strncmp(line, p->str, n)) {
                        if (p->early) {
-                               /* Already done in parse_early_param?  (Needs
-                                * exact match on param part) */
+                               /* Already done in parse_early_param?
+                                * (Needs exact match on param part).
+                                * Keep iterating, as we can have early
+                                * params and __setups of same names 8( */
                                if (line[n] == '\0' || line[n] == '=')
-                                       return 1;
+                                       had_early_param = 1;
                        } else if (!p->setup_func) {
                                printk(KERN_WARNING "Parameter %s is obsolete,"
                                       " ignored\n", p->str);
@@ -181,7 +204,8 @@ static int __init obsolete_checksetup(char *line)
                }
                p++;
        } while (p < __setup_end);
-       return 0;
+
+       return had_early_param;
 }
 
 /*
@@ -464,6 +488,7 @@ asmlinkage void __init start_kernel(void)
         * Need to run as early as possible, to initialize the
         * lockdep hash:
         */
+       unwind_init();
        lockdep_init();
 
        local_irq_disable();
@@ -502,7 +527,6 @@ asmlinkage void __init start_kernel(void)
                   __stop___param - __start___param,
                   &unknown_bootoption);
        sort_main_extable();
-       unwind_init();
        trap_init();
        rcu_init();
        init_IRQ();
index 02e6f679897282d4d16c73ed70ccb9f5e98857e5..840f8a6fb85ff1e98ee37774df42ea748465eff6 100644 (file)
@@ -115,7 +115,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mtime = inode->i_ctime = inode->i_atime =
                                CURRENT_TIME;
@@ -1275,10 +1274,7 @@ out_filesystem:
 out_sysctl:
        if (mq_sysctl_table)
                unregister_sysctl_table(mq_sysctl_table);
-       if (kmem_cache_destroy(mqueue_inode_cachep)) {
-               printk(KERN_INFO
-                       "mqueue_inode_cache: not all structures were freed\n");
-       }
+       kmem_cache_destroy(mqueue_inode_cachep);
        return error;
 }
 
index cff41511269f0dbb891fd9f460dfa2fd70c44d7a..1b32c2c04c153a056047134a28ed5f172eeb1f80 100644 (file)
@@ -289,7 +289,6 @@ static struct inode *cpuset_new_inode(mode_t mode)
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                inode->i_mapping->backing_dev_info = &cpuset_backing_dev_info;
index f9b014e3e7002e243ca8120f8f81aa33bf0f0f81..a0dad84567c9c7effe6b46f98bf077ee5d9f5e22 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/cn_proc.h>
 #include <linux/delayacct.h>
 #include <linux/taskstats_kern.h>
+#include <linux/random.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -175,6 +176,10 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
        tsk->thread_info = ti;
        setup_thread_stack(tsk, orig);
 
+#ifdef CONFIG_CC_STACKPROTECTOR
+       tsk->stack_canary = get_random_int();
+#endif
+
        /* One for us, one for whoever does the "release_task()" (usually parent) */
        atomic_set(&tsk->usage,2);
        atomic_set(&tsk->fs_excl, 0);
index 9bad178845135fba9f6b76ac59d408b723c5b5bc..c088e5542e84074d3f784108805c841c162b0ce9 100644 (file)
@@ -224,7 +224,14 @@ static int save_trace(struct stack_trace *trace)
        trace->max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries;
        trace->entries = stack_trace + nr_stack_trace_entries;
 
-       save_stack_trace(trace, NULL, 0, 3);
+       trace->skip = 3;
+       trace->all_contexts = 0;
+
+       /* Make sure to not recurse in case the the unwinder needs to tak
+e         locks. */
+       lockdep_off();
+       save_stack_trace(trace, NULL);
+       lockdep_on();
 
        trace->max_entries = trace->nr_entries;
 
index 8010b9b17aca06eba731d72ec9b44f7144e45d3d..6ceb664fb52aec50c9c2d922c5c8cf17ad5979b2 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/debug_locks.h>
 
 int panic_on_oops;
+int panic_on_unrecovered_nmi;
 int tainted;
 static int pause_on_oops;
 static int pause_on_oops_flag;
@@ -270,3 +271,15 @@ void oops_exit(void)
 {
        do_oops_enter_exit();
 }
+
+#ifdef CONFIG_CC_STACKPROTECTOR
+/*
+ * Called when gcc's -fstack-protector feature is used, and
+ * gcc detects corruption of the on-stack canary value
+ */
+void __stack_chk_fail(void)
+{
+       panic("stack-protector: Kernel stack is corrupted");
+}
+EXPORT_SYMBOL(__stack_chk_fail);
+#endif
index 93e212f20671fd3b19838327366c45e3ad54ced8..8387e8c681938a968ae005f52c58fcdf11ab17c3 100644 (file)
@@ -223,9 +223,6 @@ int fastcall attach_pid(struct task_struct *task, enum pid_type type, int nr)
        struct pid_link *link;
        struct pid *pid;
 
-       WARN_ON(!task->pid); /* to be removed soon */
-       WARN_ON(!nr); /* to be removed soon */
-
        link = &task->pids[type];
        link->pid = pid = find_pid(nr);
        hlist_add_head_rcu(&link->node, &pid->tasks[type]);
@@ -252,6 +249,15 @@ void fastcall detach_pid(struct task_struct *task, enum pid_type type)
        free_pid(pid);
 }
 
+/* transfer_pid is an optimization of attach_pid(new), detach_pid(old) */
+void fastcall transfer_pid(struct task_struct *old, struct task_struct *new,
+                          enum pid_type type)
+{
+       new->pids[type].pid = old->pids[type].pid;
+       hlist_replace_rcu(&old->pids[type].node, &new->pids[type].node);
+       old->pids[type].pid = NULL;
+}
+
 struct task_struct * fastcall pid_task(struct pid *pid, enum pid_type type)
 {
        struct task_struct *result = NULL;
index 4b6e2f18e0569321cd07d3283b9082c3a5abf298..825068ca347994570680e15f8858d590d244e61c 100644 (file)
@@ -64,6 +64,17 @@ config PM_TRACE
        CAUTION: this option will cause your machine's real-time clock to be
        set to an invalid time after a resume.
 
+config PM_SYSFS_DEPRECATED
+       bool "Driver model /sys/devices/.../power/state files (DEPRECATED)"
+       depends on PM && SYSFS
+       default n
+       help
+         The driver model started out with a sysfs file intended to provide
+         a userspace hook for device power management.  This feature has never
+         worked very well, except for limited testing purposes, and so it will
+         be removed.   It's not clear that a generic mechanism could really
+         handle the wide variability of device power states; any replacements
+         are likely to be bus or driver specific.
 
 config SOFTWARE_SUSPEND
        bool "Software Suspend"
index 7c7b9b65e365058935a5d5b77ac807b2d669df59..d72234942798e6606d613cf6c99d5fc72ab40c09 100644 (file)
@@ -103,7 +103,7 @@ static void unprepare_processes(void)
 }
 
 /**
- *     pm_suspend_disk - The granpappy of power management.
+ *     pm_suspend_disk - The granpappy of hibernation power management.
  *
  *     If we're going through the firmware, then get it over with quickly.
  *
@@ -212,7 +212,7 @@ static int software_resume(void)
 
        pr_debug("PM: Preparing devices for restore.\n");
 
-       if ((error = device_suspend(PMSG_FREEZE))) {
+       if ((error = device_suspend(PMSG_PRETHAW))) {
                printk("Some devices failed to suspend\n");
                swsusp_free();
                goto Thaw;
index 8ef677ea0ceae150ad4017ee77e485073ff995b9..0b66659dc516f13eed980412dc196781ffa6892e 100644 (file)
@@ -247,6 +247,9 @@ int swsusp_suspend(void)
        restore_processor_state();
 Restore_highmem:
        restore_highmem();
+       /* NOTE:  device_power_up() is just a resume() for devices
+        * that suspended with irqs off ... no overall powerup.
+        */
        device_power_up();
 Enable_irqs:
        local_irq_enable();
@@ -256,8 +259,12 @@ Enable_irqs:
 int swsusp_resume(void)
 {
        int error;
+
        local_irq_disable();
-       if (device_power_down(PMSG_FREEZE))
+       /* NOTE:  device_power_down() is just a suspend() with irqs off;
+        * it has no special "power things down" semantics
+        */
+       if (device_power_down(PMSG_PRETHAW))
                printk(KERN_ERR "Some devices failed to power down, very bad\n");
        /* We'll ignore saved state, but this gets preempt count (etc) right */
        save_processor_state();
index 2e4499f3e4d9a0a7c09d3caeb700c66aed671a1f..72825c853cd7251bf73fa13cbea63e78c09d8845 100644 (file)
@@ -196,7 +196,7 @@ static int snapshot_ioctl(struct inode *inode, struct file *filp,
                snapshot_free_unused_memory(&data->handle);
                down(&pm_sem);
                pm_prepare_console();
-               error = device_suspend(PMSG_FREEZE);
+               error = device_suspend(PMSG_PRETHAW);
                if (!error) {
                        error = swsusp_resume();
                        device_resume();
index 9a111f70145c6673cddf08eeaf2e86da03dff8d8..8aad0331d82eae17482a37056c0368a8e6274661 100644 (file)
@@ -241,60 +241,6 @@ int ptrace_detach(struct task_struct *child, unsigned int data)
        return 0;
 }
 
-/*
- * Access another process' address space.
- * Source/target buffer must be kernel space, 
- * Do not walk the page table directly, use get_user_pages
- */
-
-int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
-{
-       struct mm_struct *mm;
-       struct vm_area_struct *vma;
-       struct page *page;
-       void *old_buf = buf;
-
-       mm = get_task_mm(tsk);
-       if (!mm)
-               return 0;
-
-       down_read(&mm->mmap_sem);
-       /* ignore errors, just check how much was sucessfully transfered */
-       while (len) {
-               int bytes, ret, offset;
-               void *maddr;
-
-               ret = get_user_pages(tsk, mm, addr, 1,
-                               write, 1, &page, &vma);
-               if (ret <= 0)
-                       break;
-
-               bytes = len;
-               offset = addr & (PAGE_SIZE-1);
-               if (bytes > PAGE_SIZE-offset)
-                       bytes = PAGE_SIZE-offset;
-
-               maddr = kmap(page);
-               if (write) {
-                       copy_to_user_page(vma, page, addr,
-                                         maddr + offset, buf, bytes);
-                       set_page_dirty_lock(page);
-               } else {
-                       copy_from_user_page(vma, page, addr,
-                                           buf, maddr + offset, bytes);
-               }
-               kunmap(page);
-               page_cache_release(page);
-               len -= bytes;
-               buf += bytes;
-               addr += bytes;
-       }
-       up_read(&mm->mmap_sem);
-       mmput(mm);
-       
-       return buf - old_buf;
-}
-
 int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
 {
        int copied = 0;
index 33345e73485c6149f2db834fb749a7934f906442..85786ff2a4f9b1a9f79ecedb646c316a56a292e6 100644 (file)
@@ -669,7 +669,7 @@ EXPORT_SYMBOL_GPL(relay_flush);
  */
 static int relay_file_open(struct inode *inode, struct file *filp)
 {
-       struct rchan_buf *buf = inode->u.generic_ip;
+       struct rchan_buf *buf = inode->i_private;
        kref_get(&buf->kref);
        filp->private_data = buf;
 
index 46286434af8066af359143df81244e0c3024de19..9db38a1a75208cb36bb8c68cd51f6ba7b293ce5f 100644 (file)
@@ -344,12 +344,11 @@ EXPORT_SYMBOL(allocate_resource);
  *
  * Returns 0 on success, -EBUSY if the resource can't be inserted.
  *
- * This function is equivalent of request_resource when no conflict
+ * This function is equivalent to request_resource when no conflict
  * happens. If a conflict happens, and the conflicting resources
  * entirely fit within the range of the new resource, then the new
- * resource is inserted and the conflicting resources become childs of
- * the new resource.  Otherwise the new resource becomes the child of
- * the conflicting resource
+ * resource is inserted and the conflicting resources become children of
+ * the new resource.
  */
 int insert_resource(struct resource *parent, struct resource *new)
 {
@@ -357,20 +356,21 @@ int insert_resource(struct resource *parent, struct resource *new)
        struct resource *first, *next;
 
        write_lock(&resource_lock);
- begin:
-       result = 0;
-       first = __request_resource(parent, new);
-       if (!first)
-               goto out;
 
-       result = -EBUSY;
-       if (first == parent)
-               goto out;
+       for (;; parent = first) {
+               result = 0;
+               first = __request_resource(parent, new);
+               if (!first)
+                       goto out;
 
-       /* Resource fully contained by the clashing resource? Recurse into it */
-       if (first->start <= new->start && first->end >= new->end) {
-               parent = first;
-               goto begin;
+               result = -EBUSY;
+               if (first == parent)
+                       goto out;
+
+               if ((first->start > new->start) || (first->end < new->end))
+                       break;
+               if ((first->start == new->start) && (first->end == new->end))
+                       break;
        }
 
        for (next = first; ; next = next->sibling) {
index bfdb5686fa3e4e3d23075afd2bf21bf680ba0aae..05853a7337e3268be684ae2f53248b6e9fc75e56 100644 (file)
@@ -2577,6 +2577,11 @@ asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
 }
 #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
 
+__attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma)
+{
+       return NULL;
+}
+
 void __init signals_init(void)
 {
        sigqueue_cachep =
index fb524b009eefeca3ffd2a2a929421a7eeb997660..9644a41e0bef60fd40773976705c6529b49c45d1 100644 (file)
@@ -7,6 +7,11 @@
  *
  * This file contains the spinlock/rwlock implementations for the
  * SMP and the DEBUG_SPINLOCK cases. (UP-nondebug inlines them)
+ *
+ * Note that some architectures have special knowledge about the
+ * stack frames of these functions in their profile_pc. If you
+ * change anything significant here that could change the stack
+ * frame contact the architecture maintainers.
  */
 
 #include <linux/linkage.h>
index e236f98f7ec5d5460fa5eda7d97155bfb712df61..3f894775488dd7fb62907d149d0d1959b67de049 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/tty.h>
 #include <linux/signal.h>
 #include <linux/cn_proc.h>
+#include <linux/getcpu.h>
 
 #include <linux/compat.h>
 #include <linux/syscalls.h>
@@ -2062,3 +2063,33 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
        }
        return error;
 }
+
+asmlinkage long sys_getcpu(unsigned __user *cpup, unsigned __user *nodep,
+                          struct getcpu_cache __user *cache)
+{
+       int err = 0;
+       int cpu = raw_smp_processor_id();
+       if (cpup)
+               err |= put_user(cpu, cpup);
+       if (nodep)
+               err |= put_user(cpu_to_node(cpu), nodep);
+       if (cache) {
+               /*
+                * The cache is not needed for this implementation,
+                * but make sure user programs pass something
+                * valid. vsyscall implementations can instead make
+                * good use of the cache. Only use t0 and t1 because
+                * these are available in both 32bit and 64bit ABI (no
+                * need for a compat_getcpu). 32bit has enough
+                * padding
+                */
+               unsigned long t0, t1;
+               get_user(t0, &cache->t0);
+               get_user(t1, &cache->t1);
+               t0++;
+               t1++;
+               put_user(t0, &cache->t0);
+               put_user(t1, &cache->t1);
+       }
+       return err ? -EFAULT : 0;
+}
index fd43c3e6786b5b19c8ff173b45638c56392c7d86..8bfa7d117c54fb8ef2b0e5e458caf3303e17b366 100644 (file)
@@ -76,8 +76,9 @@ extern int compat_log;
 
 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86)
 int unknown_nmi_panic;
-extern int proc_unknown_nmi_panic(ctl_table *, int, struct file *,
-                                 void __user *, size_t *, loff_t *);
+int nmi_watchdog_enabled;
+extern int proc_nmi_enabled(struct ctl_table *, int , struct file *,
+                       void __user *, size_t *, loff_t *);
 #endif
 
 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
@@ -136,8 +137,11 @@ extern int no_unaligned_warning;
 extern int max_lock_depth;
 #endif
 
-static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t,
-                      ctl_table *, void **);
+#ifdef CONFIG_SYSCTL_SYSCALL
+static int parse_table(int __user *, int, void __user *, size_t __user *,
+               void __user *, size_t, ctl_table *, void **);
+#endif
+
 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
                  void __user *buffer, size_t *lenp, loff_t *ppos);
 
@@ -164,7 +168,7 @@ int sysctl_legacy_va_layout;
 
 /* /proc declarations: */
 
-#ifdef CONFIG_PROC_FS
+#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 *);
@@ -628,10 +632,26 @@ static ctl_table kern_table[] = {
                .data           = &unknown_nmi_panic,
                .maxlen         = sizeof (int),
                .mode           = 0644,
-               .proc_handler   = &proc_unknown_nmi_panic,
+               .proc_handler   = &proc_dointvec,
+       },
+       {
+               .ctl_name       = KERN_NMI_WATCHDOG,
+               .procname       = "nmi_watchdog",
+               .data           = &nmi_watchdog_enabled,
+               .maxlen         = sizeof (int),
+               .mode           = 0644,
+               .proc_handler   = &proc_nmi_enabled,
        },
 #endif
 #if defined(CONFIG_X86)
+       {
+               .ctl_name       = KERN_PANIC_ON_NMI,
+               .procname       = "panic_on_unrecovered_nmi",
+               .data           = &panic_on_unrecovered_nmi,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec,
+       },
        {
                .ctl_name       = KERN_BOOTLOADER_TYPE,
                .procname       = "bootloader_type",
@@ -1149,12 +1169,13 @@ static void start_unregistering(struct ctl_table_header *p)
 
 void __init sysctl_init(void)
 {
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_PROC_SYSCTL
        register_proc_table(root_table, proc_sys_root, &root_table_header);
        init_irq_proc();
 #endif
 }
 
+#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)
 {
@@ -1208,6 +1229,7 @@ asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
        unlock_kernel();
        return error;
 }
+#endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*
  * ctl_perm does NOT grant the superuser all rights automatically, because
@@ -1234,6 +1256,7 @@ static inline int ctl_perm(ctl_table *table, int op)
        return test_perm(table->mode, op);
 }
 
+#ifdef CONFIG_SYSCTL_SYSCALL
 static int parse_table(int __user *name, int nlen,
                       void __user *oldval, size_t __user *oldlenp,
                       void __user *newval, size_t newlen,
@@ -1323,6 +1346,7 @@ int do_sysctl_strategy (ctl_table *table,
        }
        return 0;
 }
+#endif /* CONFIG_SYSCTL_SYSCALL */
 
 /**
  * register_sysctl_table - register a sysctl hierarchy
@@ -1410,7 +1434,7 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table,
        else
                list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
        spin_unlock(&sysctl_lock);
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_PROC_SYSCTL
        register_proc_table(table, proc_sys_root, tmp);
 #endif
        return tmp;
@@ -1428,18 +1452,31 @@ void unregister_sysctl_table(struct ctl_table_header * header)
        might_sleep();
        spin_lock(&sysctl_lock);
        start_unregistering(header);
-#ifdef CONFIG_PROC_FS
+#ifdef CONFIG_PROC_SYSCTL
        unregister_proc_table(header->ctl_table, proc_sys_root);
 #endif
        spin_unlock(&sysctl_lock);
        kfree(header);
 }
 
+#else /* !CONFIG_SYSCTL */
+struct ctl_table_header * register_sysctl_table(ctl_table * table,
+                                               int insert_at_head)
+{
+       return NULL;
+}
+
+void unregister_sysctl_table(struct ctl_table_header * table)
+{
+}
+
+#endif /* CONFIG_SYSCTL */
+
 /*
  * /proc/sys support
  */
 
-#ifdef CONFIG_PROC_FS
+#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)
@@ -2301,6 +2338,7 @@ int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
 #endif /* CONFIG_PROC_FS */
 
 
+#ifdef CONFIG_SYSCTL_SYSCALL
 /*
  * General sysctl support routines 
  */
@@ -2443,11 +2481,19 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
        return 1;
 }
 
-#else /* CONFIG_SYSCTL */
+#else /* CONFIG_SYSCTL_SYSCALL */
 
 
 asmlinkage long sys_sysctl(struct __sysctl_args __user *args)
 {
+       static int msg_count;
+
+       if (msg_count < 5) {
+               msg_count++;
+               printk(KERN_INFO
+                       "warning: process `%s' used the removed sysctl "
+                       "system call\n", current->comm);
+       }
        return -ENOSYS;
 }
 
@@ -2479,73 +2525,7 @@ int sysctl_ms_jiffies(ctl_table *table, int __user *name, int nlen,
        return -ENOSYS;
 }
 
-int proc_dostring(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec(ctl_table *table, int write, struct file *filp,
-                 void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
-                       void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
-                   void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
-                         void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp,
-                         void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_dointvec_ms_jiffies(ctl_table *table, int write, struct file *filp,
-                            void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_doulongvec_minmax(ctl_table *table, int write, struct file *filp,
-                   void __user *buffer, size_t *lenp, loff_t *ppos)
-{
-       return -ENOSYS;
-}
-
-int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
-                                     struct file *filp,
-                                     void __user *buffer,
-                                     size_t *lenp, loff_t *ppos)
-{
-    return -ENOSYS;
-}
-
-struct ctl_table_header * register_sysctl_table(ctl_table * table, 
-                                               int insert_at_head)
-{
-       return NULL;
-}
-
-void unregister_sysctl_table(struct ctl_table_header * table)
-{
-}
-
-#endif /* CONFIG_SYSCTL */
+#endif /* CONFIG_SYSCTL_SYSCALL */
 
 /*
  * No sense putting this after each symbol definition, twice,
index f69c804c8e620c5037ba5896a69568a426bca067..3430475fcd886d011c01370a558e0a5965dd950d 100644 (file)
@@ -603,6 +603,7 @@ int unwind(struct unwind_frame_info *frame)
 #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
        const u32 *fde = NULL, *cie = NULL;
        const u8 *ptr = NULL, *end = NULL;
+       unsigned long pc = UNW_PC(frame) - frame->call_frame;
        unsigned long startLoc = 0, endLoc = 0, cfa;
        unsigned i;
        signed ptrType = -1;
@@ -612,7 +613,7 @@ int unwind(struct unwind_frame_info *frame)
 
        if (UNW_PC(frame) == 0)
                return -EINVAL;
-       if ((table = find_table(UNW_PC(frame))) != NULL
+       if ((table = find_table(pc)) != NULL
            && !(table->size & (sizeof(*fde) - 1))) {
                unsigned long tableSize = table->size;
 
@@ -647,7 +648,7 @@ int unwind(struct unwind_frame_info *frame)
                                                ptrType & DW_EH_PE_indirect
                                                ? ptrType
                                                : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed));
-                       if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc)
+                       if (pc >= startLoc && pc < endLoc)
                                break;
                        cie = NULL;
                }
@@ -657,16 +658,28 @@ int unwind(struct unwind_frame_info *frame)
                state.cieEnd = ptr; /* keep here temporarily */
                ptr = (const u8 *)(cie + 2);
                end = (const u8 *)(cie + 1) + *cie;
+               frame->call_frame = 1;
                if ((state.version = *ptr) != 1)
                        cie = NULL; /* unsupported version */
                else if (*++ptr) {
                        /* check if augmentation size is first (and thus present) */
                        if (*ptr == 'z') {
-                               /* check for ignorable (or already handled)
-                                * nul-terminated augmentation string */
-                               while (++ptr < end && *ptr)
-                                       if (strchr("LPR", *ptr) == NULL)
+                               while (++ptr < end && *ptr) {
+                                       switch(*ptr) {
+                                       /* check for ignorable (or already handled)
+                                        * nul-terminated augmentation string */
+                                       case 'L':
+                                       case 'P':
+                                       case 'R':
+                                               continue;
+                                       case 'S':
+                                               frame->call_frame = 0;
+                                               continue;
+                                       default:
                                                break;
+                                       }
+                                       break;
+                               }
                        }
                        if (ptr >= end || *ptr)
                                cie = NULL;
@@ -755,7 +768,7 @@ int unwind(struct unwind_frame_info *frame)
        state.org = startLoc;
        memcpy(&state.cfa, &badCFA, sizeof(state.cfa));
        /* process instructions */
-       if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state)
+       if (!processCFI(ptr, end, pc, ptrType, &state)
           || state.loc > endLoc
           || state.regs[retAddrReg].where == Nowhere
           || state.cfa.reg >= ARRAY_SIZE(reg_info)
@@ -763,6 +776,11 @@ int unwind(struct unwind_frame_info *frame)
           || state.cfa.offs % sizeof(unsigned long))
                return -EIO;
        /* update frame */
+#ifndef CONFIG_AS_CFI_SIGNAL_FRAME
+       if(frame->call_frame
+          && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign))
+               frame->call_frame = 0;
+#endif
        cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs;
        startLoc = min((unsigned long)UNW_SP(frame), cfa);
        endLoc = max((unsigned long)UNW_SP(frame), cfa);
@@ -866,6 +884,7 @@ int unwind_init_frame_info(struct unwind_frame_info *info,
                            /*const*/ struct pt_regs *regs)
 {
        info->task = tsk;
+       info->call_frame = 0;
        arch_unw_init_frame_info(info, regs);
 
        return 0;
@@ -879,6 +898,7 @@ int unwind_init_blocked(struct unwind_frame_info *info,
                         struct task_struct *tsk)
 {
        info->task = tsk;
+       info->call_frame = 0;
        arch_unw_init_blocked(info);
 
        return 0;
@@ -894,6 +914,7 @@ int unwind_init_running(struct unwind_frame_info *info,
                         void *arg)
 {
        info->task = current;
+       info->call_frame = 0;
 
        return arch_unwind_init_running(info, callback, arg);
 }
index 3f21cc79a1346b40e03d75c9d2e764925dff9dd0..b0f5ca72599fee5f4ed868457a85c39b5f6e57ef 100644 (file)
@@ -8,6 +8,13 @@ config PRINTK_TIME
          operations.  This is useful for identifying long delays
          in kernel startup.
 
+config ENABLE_MUST_CHECK
+       bool "Enable __must_check logic"
+       default y
+       help
+         Enable the __must_check logic in the kernel build.  Disable this to
+         suppress the "warning: ignoring return value of 'foo', declared with
+         attribute warn_unused_result" messages.
 
 config MAGIC_SYSRQ
        bool "Magic SysRq key"
@@ -218,7 +225,7 @@ config LOCKDEP
        bool
        depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
        select STACKTRACE
-       select FRAME_POINTER
+       select FRAME_POINTER if !X86
        select KALLSYMS
        select KALLSYMS_ALL
 
@@ -277,7 +284,7 @@ config DEBUG_HIGHMEM
 config DEBUG_BUGVERBOSE
        bool "Verbose BUG() reporting (adds 70K)" if DEBUG_KERNEL && EMBEDDED
        depends on BUG
-       depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV
+       depends on ARM || ARM26 || AVR32 || M32R || M68K || SPARC32 || SPARC64 || X86_32 || FRV || SUPERH
        default !EMBEDDED
        help
          Say Y here to make BUG() panics output the file name and line number
@@ -315,7 +322,7 @@ config DEBUG_VM
 
 config FRAME_POINTER
        bool "Compile the kernel with frame pointers"
-       depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32)
+       depends on DEBUG_KERNEL && (X86 || CRIS || M68K || M68KNOMMU || FRV || UML || S390 || AVR32 || SUPERH)
        default y if DEBUG_INFO && UML
        help
          If you say Y here the resulting kernel image will be slightly larger
index 4382576717086eeaaa48d928db67dfb6757cbbb7..360556a7803d4dae582b39edec3e91bb78ac7749 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/module.h>
 #include <asm/types.h>
+#include <asm/bitops.h>
 
 /**
  * hweightN - returns the hamming weight of a N-bit word
@@ -40,14 +41,19 @@ unsigned long hweight64(__u64 w)
 #if BITS_PER_LONG == 32
        return hweight32((unsigned int)(w >> 32)) + hweight32((unsigned int)w);
 #elif BITS_PER_LONG == 64
+#ifdef ARCH_HAS_FAST_MULTIPLIER
+       w -= (w >> 1) & 0x5555555555555555ul;
+       w =  (w & 0x3333333333333333ul) + ((w >> 2) & 0x3333333333333333ul);
+       w =  (w + (w >> 4)) & 0x0f0f0f0f0f0f0f0ful;
+       return (w * 0x0101010101010101ul) >> 56;
+#else
        __u64 res = w - ((w >> 1) & 0x5555555555555555ul);
        res = (res & 0x3333333333333333ul) + ((res >> 2) & 0x3333333333333333ul);
        res = (res + (res >> 4)) & 0x0F0F0F0F0F0F0F0Ful;
        res = res + (res >> 8);
        res = res + (res >> 16);
        return (res + (res >> 32)) & 0x00000000000000FFul;
-#else
-#error BITS_PER_LONG not defined
+#endif
 #endif
 }
 EXPORT_SYMBOL(hweight64);
index 9c94f0b163a11a713299f97876012296f63d51d7..120bd175aa7855044fdb5a440b6fc189b21344b3 100644 (file)
@@ -123,12 +123,10 @@ EXPORT_SYMBOL_GPL(klist_add_tail);
 static void klist_release(struct kref * kref)
 {
        struct klist_node * n = container_of(kref, struct klist_node, n_ref);
-       void (*put)(struct klist_node *) = n->n_klist->put;
+
        list_del(&n->n_node);
        complete(&n->n_removed);
        n->n_klist = NULL;
-       if (put)
-               put(n);
 }
 
 static int klist_dec_and_del(struct klist_node * n)
@@ -145,10 +143,14 @@ static int klist_dec_and_del(struct klist_node * n)
 void klist_del(struct klist_node * n)
 {
        struct klist * k = n->n_klist;
+       void (*put)(struct klist_node *) = k->put;
 
        spin_lock(&k->k_lock);
-       klist_dec_and_del(n);
+       if (!klist_dec_and_del(n))
+               put = NULL;
        spin_unlock(&k->k_lock);
+       if (put)
+               put(n);
 }
 
 EXPORT_SYMBOL_GPL(klist_del);
@@ -161,10 +163,7 @@ EXPORT_SYMBOL_GPL(klist_del);
 
 void klist_remove(struct klist_node * n)
 {
-       struct klist * k = n->n_klist;
-       spin_lock(&k->k_lock);
-       klist_dec_and_del(n);
-       spin_unlock(&k->k_lock);
+       klist_del(n);
        wait_for_completion(&n->n_removed);
 }
 
@@ -260,12 +259,15 @@ static struct klist_node * to_klist_node(struct list_head * n)
 struct klist_node * klist_next(struct klist_iter * i)
 {
        struct list_head * next;
+       struct klist_node * lnode = i->i_cur;
        struct klist_node * knode = NULL;
+       void (*put)(struct klist_node *) = i->i_klist->put;
 
        spin_lock(&i->i_klist->k_lock);
-       if (i->i_cur) {
-               next = i->i_cur->n_node.next;
-               klist_dec_and_del(i->i_cur);
+       if (lnode) {
+               next = lnode->n_node.next;
+               if (!klist_dec_and_del(lnode))
+                       put = NULL;
        } else
                next = i->i_head->next;
 
@@ -275,6 +277,8 @@ struct klist_node * klist_next(struct klist_iter * i)
        }
        i->i_cur = knode;
        spin_unlock(&i->i_klist->k_lock);
+       if (put && lnode)
+               put(lnode);
        return knode;
 }
 
index 8e7c7199348749e63bb4cf17868e2123aa2c44fc..1699eb9161f34594a38cc28fbea1f0ab2db56893 100644 (file)
@@ -407,6 +407,7 @@ static struct kobj_type dir_ktype = {
 struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
 {
        struct kobject *k;
+       int ret;
 
        if (!parent)
                return NULL;
@@ -418,7 +419,13 @@ struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
        k->parent = parent;
        k->ktype = &dir_ktype;
        kobject_set_name(k, name);
-       kobject_register(k);
+       ret = kobject_register(k);
+       if (ret < 0) {
+               printk(KERN_WARNING "kobject_add_dir: "
+                       "kobject_register error: %d\n", ret);
+               kobject_del(k);
+               return NULL;
+       }
 
        return k;
 }
index 92a3ebd8d7951daff767f409836c8490cf283028..601159a46ab64e538dc1c2cbe710776e3ecb5208 100644 (file)
@@ -2255,6 +2255,54 @@ oom:
        return VM_FAULT_OOM;
 }
 
+/*
+ * do_no_pfn() tries to create a new page mapping for a page without
+ * a struct_page backing it
+ *
+ * As this is called only for pages that do not currently exist, we
+ * do not need to flush old virtual caches or the TLB.
+ *
+ * We enter with non-exclusive mmap_sem (to exclude vma changes,
+ * but allow concurrent faults), and pte mapped but not yet locked.
+ * We return with mmap_sem still held, but pte unmapped and unlocked.
+ *
+ * It is expected that the ->nopfn handler always returns the same pfn
+ * for a given virtual mapping.
+ *
+ * Mark this `noinline' to prevent it from bloating the main pagefault code.
+ */
+static noinline int do_no_pfn(struct mm_struct *mm, struct vm_area_struct *vma,
+                    unsigned long address, pte_t *page_table, pmd_t *pmd,
+                    int write_access)
+{
+       spinlock_t *ptl;
+       pte_t entry;
+       unsigned long pfn;
+       int ret = VM_FAULT_MINOR;
+
+       pte_unmap(page_table);
+       BUG_ON(!(vma->vm_flags & VM_PFNMAP));
+       BUG_ON(is_cow_mapping(vma->vm_flags));
+
+       pfn = vma->vm_ops->nopfn(vma, address & PAGE_MASK);
+       if (pfn == NOPFN_OOM)
+               return VM_FAULT_OOM;
+       if (pfn == NOPFN_SIGBUS)
+               return VM_FAULT_SIGBUS;
+
+       page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
+
+       /* Only go through if we didn't race with anybody else... */
+       if (pte_none(*page_table)) {
+               entry = pfn_pte(pfn, vma->vm_page_prot);
+               if (write_access)
+                       entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+               set_pte_at(mm, address, page_table, entry);
+       }
+       pte_unmap_unlock(page_table, ptl);
+       return ret;
+}
+
 /*
  * Fault of a previously existing named mapping. Repopulate the pte
  * from the encoded file_pte if possible. This enables swappable
@@ -2317,11 +2365,17 @@ static inline int handle_pte_fault(struct mm_struct *mm,
        old_entry = entry = *pte;
        if (!pte_present(entry)) {
                if (pte_none(entry)) {
-                       if (!vma->vm_ops || !vma->vm_ops->nopage)
-                               return do_anonymous_page(mm, vma, address,
-                                       pte, pmd, write_access);
-                       return do_no_page(mm, vma, address,
-                                       pte, pmd, write_access);
+                       if (vma->vm_ops) {
+                               if (vma->vm_ops->nopage)
+                                       return do_no_page(mm, vma, address,
+                                                         pte, pmd,
+                                                         write_access);
+                               if (unlikely(vma->vm_ops->nopfn))
+                                       return do_no_pfn(mm, vma, address, pte,
+                                                        pmd, write_access);
+                       }
+                       return do_anonymous_page(mm, vma, address,
+                                                pte, pmd, write_access);
                }
                if (pte_file(entry))
                        return do_file_page(mm, vma, address,
@@ -2550,3 +2604,56 @@ int in_gate_area_no_task(unsigned long addr)
 }
 
 #endif /* __HAVE_ARCH_GATE_AREA */
+
+/*
+ * Access another process' address space.
+ * Source/target buffer must be kernel space,
+ * Do not walk the page table directly, use get_user_pages
+ */
+int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
+{
+       struct mm_struct *mm;
+       struct vm_area_struct *vma;
+       struct page *page;
+       void *old_buf = buf;
+
+       mm = get_task_mm(tsk);
+       if (!mm)
+               return 0;
+
+       down_read(&mm->mmap_sem);
+       /* ignore errors, just check how much was sucessfully transfered */
+       while (len) {
+               int bytes, ret, offset;
+               void *maddr;
+
+               ret = get_user_pages(tsk, mm, addr, 1,
+                               write, 1, &page, &vma);
+               if (ret <= 0)
+                       break;
+
+               bytes = len;
+               offset = addr & (PAGE_SIZE-1);
+               if (bytes > PAGE_SIZE-offset)
+                       bytes = PAGE_SIZE-offset;
+
+               maddr = kmap(page);
+               if (write) {
+                       copy_to_user_page(vma, page, addr,
+                                         maddr + offset, buf, bytes);
+                       set_page_dirty_lock(page);
+               } else {
+                       copy_from_user_page(vma, page, addr,
+                                           buf, maddr + offset, bytes);
+               }
+               kunmap(page);
+               page_cache_release(page);
+               len -= bytes;
+               buf += bytes;
+               addr += bytes;
+       }
+       up_read(&mm->mmap_sem);
+       mmput(mm);
+
+       return buf - old_buf;
+}
index 38f89650bc84962d9209b5035297b173c3b16c44..cf18f0942553554ae4977958dc06109335eb8abd 100644 (file)
@@ -1136,7 +1136,9 @@ static unsigned interleave_nodes(struct mempolicy *policy)
  */
 unsigned slab_node(struct mempolicy *policy)
 {
-       switch (policy->policy) {
+       int pol = policy ? policy->policy : MPOL_DEFAULT;
+
+       switch (pol) {
        case MPOL_INTERLEAVE:
                return interleave_nodes(policy);
 
index d99dea31e443f2505ce97b967c69681f2ae1e359..564540662192290b67f4a000c969407c404e86ad 100644 (file)
@@ -122,26 +122,50 @@ unsigned int kobjsize(const void *objp)
 }
 
 /*
- * The nommu dodgy version :-)
+ * get a list of pages in an address range belonging to the specified process
+ * and indicate the VMA that covers each page
+ * - this is potentially dodgy as we may end incrementing the page count of a
+ *   slab page or a secondary page from a compound page
+ * - don't permit access to VMAs that don't support it, such as I/O mappings
  */
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        unsigned long start, int len, int write, int force,
        struct page **pages, struct vm_area_struct **vmas)
 {
+       struct vm_area_struct *vma;
+       unsigned long vm_flags;
        int i;
-       static struct vm_area_struct dummy_vma;
+
+       /* calculate required read or write permissions.
+        * - if 'force' is set, we only require the "MAY" flags.
+        */
+       vm_flags  = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
+       vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
 
        for (i = 0; i < len; i++) {
+               vma = find_vma(mm, start);
+               if (!vma)
+                       goto finish_or_fault;
+
+               /* protect what we can, including chardevs */
+               if (vma->vm_flags & (VM_IO | VM_PFNMAP) ||
+                   !(vm_flags & vma->vm_flags))
+                       goto finish_or_fault;
+
                if (pages) {
                        pages[i] = virt_to_page(start);
                        if (pages[i])
                                page_cache_get(pages[i]);
                }
                if (vmas)
-                       vmas[i] = &dummy_vma;
+                       vmas[i] = vma;
                start += PAGE_SIZE;
        }
-       return(i);
+
+       return i;
+
+finish_or_fault:
+       return i ? : -EFAULT;
 }
 
 EXPORT_SYMBOL(get_user_pages);
@@ -286,6 +310,77 @@ static void show_process_blocks(void)
 }
 #endif /* DEBUG */
 
+/*
+ * add a VMA into a process's mm_struct in the appropriate place in the list
+ * - should be called with mm->mmap_sem held writelocked
+ */
+static void add_vma_to_mm(struct mm_struct *mm, struct vm_list_struct *vml)
+{
+       struct vm_list_struct **ppv;
+
+       for (ppv = &current->mm->context.vmlist; *ppv; ppv = &(*ppv)->next)
+               if ((*ppv)->vma->vm_start > vml->vma->vm_start)
+                       break;
+
+       vml->next = *ppv;
+       *ppv = vml;
+}
+
+/*
+ * look up the first VMA in which addr resides, NULL if none
+ * - should be called with mm->mmap_sem at least held readlocked
+ */
+struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
+{
+       struct vm_list_struct *loop, *vml;
+
+       /* search the vm_start ordered list */
+       vml = NULL;
+       for (loop = mm->context.vmlist; loop; loop = loop->next) {
+               if (loop->vma->vm_start > addr)
+                       break;
+               vml = loop;
+       }
+
+       if (vml && vml->vma->vm_end > addr)
+               return vml->vma;
+
+       return NULL;
+}
+EXPORT_SYMBOL(find_vma);
+
+/*
+ * find a VMA
+ * - we don't extend stack VMAs under NOMMU conditions
+ */
+struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
+{
+       return find_vma(mm, addr);
+}
+
+/*
+ * look up the first VMA exactly that exactly matches addr
+ * - should be called with mm->mmap_sem at least held readlocked
+ */
+static inline struct vm_area_struct *find_vma_exact(struct mm_struct *mm,
+                                                   unsigned long addr)
+{
+       struct vm_list_struct *vml;
+
+       /* search the vm_start ordered list */
+       for (vml = mm->context.vmlist; vml; vml = vml->next) {
+               if (vml->vma->vm_start == addr)
+                       return vml->vma;
+               if (vml->vma->vm_start > addr)
+                       break;
+       }
+
+       return NULL;
+}
+
+/*
+ * find a VMA in the global tree
+ */
 static inline struct vm_area_struct *find_nommu_vma(unsigned long start)
 {
        struct vm_area_struct *vma;
@@ -305,6 +400,9 @@ static inline struct vm_area_struct *find_nommu_vma(unsigned long start)
        return NULL;
 }
 
+/*
+ * add a VMA in the global tree
+ */
 static void add_nommu_vma(struct vm_area_struct *vma)
 {
        struct vm_area_struct *pvma;
@@ -351,6 +449,9 @@ static void add_nommu_vma(struct vm_area_struct *vma)
        rb_insert_color(&vma->vm_rb, &nommu_vma_tree);
 }
 
+/*
+ * delete a VMA from the global list
+ */
 static void delete_nommu_vma(struct vm_area_struct *vma)
 {
        struct address_space *mapping;
@@ -828,8 +929,7 @@ unsigned long do_mmap_pgoff(struct file *file,
        realalloc += kobjsize(vml);
        askedalloc += sizeof(*vml);
 
-       vml->next = current->mm->context.vmlist;
-       current->mm->context.vmlist = vml;
+       add_vma_to_mm(current->mm, vml);
 
        up_write(&nommu_vma_sem);
 
@@ -908,6 +1008,11 @@ static void put_vma(struct vm_area_struct *vma)
        }
 }
 
+/*
+ * release a mapping
+ * - under NOMMU conditions the parameters must match exactly to the mapping to
+ *   be removed
+ */
 int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
 {
        struct vm_list_struct *vml, **parent;
@@ -917,10 +1022,13 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
        printk("do_munmap:\n");
 #endif
 
-       for (parent = &mm->context.vmlist; *parent; parent = &(*parent)->next)
+       for (parent = &mm->context.vmlist; *parent; parent = &(*parent)->next) {
+               if ((*parent)->vma->vm_start > addr)
+                       break;
                if ((*parent)->vma->vm_start == addr &&
                    ((len == 0) || ((*parent)->vma->vm_end == end)))
                        goto found;
+       }
 
        printk("munmap of non-mmaped memory by process %d (%s): %p\n",
               current->pid, current->comm, (void *) addr);
@@ -946,7 +1054,20 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
        return 0;
 }
 
-/* Release all mmaps. */
+asmlinkage long sys_munmap(unsigned long addr, size_t len)
+{
+       int ret;
+       struct mm_struct *mm = current->mm;
+
+       down_write(&mm->mmap_sem);
+       ret = do_munmap(mm, addr, len);
+       up_write(&mm->mmap_sem);
+       return ret;
+}
+
+/*
+ * Release all mappings
+ */
 void exit_mmap(struct mm_struct * mm)
 {
        struct vm_list_struct *tmp;
@@ -973,37 +1094,26 @@ void exit_mmap(struct mm_struct * mm)
        }
 }
 
-asmlinkage long sys_munmap(unsigned long addr, size_t len)
-{
-       int ret;
-       struct mm_struct *mm = current->mm;
-
-       down_write(&mm->mmap_sem);
-       ret = do_munmap(mm, addr, len);
-       up_write(&mm->mmap_sem);
-       return ret;
-}
-
 unsigned long do_brk(unsigned long addr, unsigned long len)
 {
        return -ENOMEM;
 }
 
 /*
- * Expand (or shrink) an existing mapping, potentially moving it at the
- * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
+ * expand (or shrink) an existing mapping, potentially moving it at the same
+ * time (controlled by the MREMAP_MAYMOVE flag and available VM space)
  *
- * MREMAP_FIXED option added 5-Dec-1999 by Benjamin LaHaise
- * This option implies MREMAP_MAYMOVE.
+ * under NOMMU conditions, we only permit changing a mapping's size, and only
+ * as long as it stays within the hole allocated by the kmalloc() call in
+ * do_mmap_pgoff() and the block is not shareable
  *
- * on uClinux, we only permit changing a mapping's size, and only as long as it stays within the
- * hole allocated by the kmalloc() call in do_mmap_pgoff() and the block is not shareable
+ * MREMAP_FIXED is not supported under NOMMU conditions
  */
 unsigned long do_mremap(unsigned long addr,
                        unsigned long old_len, unsigned long new_len,
                        unsigned long flags, unsigned long new_addr)
 {
-       struct vm_list_struct *vml = NULL;
+       struct vm_area_struct *vma;
 
        /* insanity checks first */
        if (new_len == 0)
@@ -1012,58 +1122,46 @@ unsigned long do_mremap(unsigned long addr,
        if (flags & MREMAP_FIXED && new_addr != addr)
                return (unsigned long) -EINVAL;
 
-       for (vml = current->mm->context.vmlist; vml; vml = vml->next)
-               if (vml->vma->vm_start == addr)
-                       goto found;
-
-       return (unsigned long) -EINVAL;
+       vma = find_vma_exact(current->mm, addr);
+       if (!vma)
+               return (unsigned long) -EINVAL;
 
- found:
-       if (vml->vma->vm_end != vml->vma->vm_start + old_len)
+       if (vma->vm_end != vma->vm_start + old_len)
                return (unsigned long) -EFAULT;
 
-       if (vml->vma->vm_flags & VM_MAYSHARE)
+       if (vma->vm_flags & VM_MAYSHARE)
                return (unsigned long) -EPERM;
 
        if (new_len > kobjsize((void *) addr))
                return (unsigned long) -ENOMEM;
 
        /* all checks complete - do it */
-       vml->vma->vm_end = vml->vma->vm_start + new_len;
+       vma->vm_end = vma->vm_start + new_len;
 
        askedalloc -= old_len;
        askedalloc += new_len;
 
-       return vml->vma->vm_start;
+       return vma->vm_start;
 }
 
-/*
- * Look up the first VMA which satisfies  addr < vm_end,  NULL if none
- */
-struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
+asmlinkage unsigned long sys_mremap(unsigned long addr,
+       unsigned long old_len, unsigned long new_len,
+       unsigned long flags, unsigned long new_addr)
 {
-       struct vm_list_struct *vml;
-
-       for (vml = mm->context.vmlist; vml; vml = vml->next)
-               if (addr >= vml->vma->vm_start && addr < vml->vma->vm_end)
-                       return vml->vma;
+       unsigned long ret;
 
-       return NULL;
+       down_write(&current->mm->mmap_sem);
+       ret = do_mremap(addr, old_len, new_len, flags, new_addr);
+       up_write(&current->mm->mmap_sem);
+       return ret;
 }
 
-EXPORT_SYMBOL(find_vma);
-
 struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
                        unsigned int foll_flags)
 {
        return NULL;
 }
 
-struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
-{
-       return NULL;
-}
-
 int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
                unsigned long to, unsigned long size, pgprot_t prot)
 {
@@ -1206,3 +1304,44 @@ struct page *filemap_nopage(struct vm_area_struct *area,
        BUG();
        return NULL;
 }
+
+/*
+ * Access another process' address space.
+ * - source/target buffer must be kernel space
+ */
+int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
+{
+       struct vm_area_struct *vma;
+       struct mm_struct *mm;
+
+       if (addr + len < addr)
+               return 0;
+
+       mm = get_task_mm(tsk);
+       if (!mm)
+               return 0;
+
+       down_read(&mm->mmap_sem);
+
+       /* the access must start within one of the target process's mappings */
+       vma = find_vma(mm, addr);
+       if (vma) {
+               /* don't overrun this mapping */
+               if (addr + len >= vma->vm_end)
+                       len = vma->vm_end - addr;
+
+               /* only read or write mappings where it is permitted */
+               if (write && vma->vm_flags & VM_MAYWRITE)
+                       len -= copy_to_user((void *) addr, buf, len);
+               else if (!write && vma->vm_flags & VM_MAYREAD)
+                       len -= copy_from_user(buf, (void *) addr, len);
+               else
+                       len = 0;
+       } else {
+               len = 0;
+       }
+
+       up_read(&mm->mmap_sem);
+       mmput(mm);
+       return len;
+}
index 9810f0a60db7720da211386298422e138341e16e..4f59d90b81e65a314e0433dc61371b785b3df61f 100644 (file)
@@ -37,6 +37,8 @@
 #include <linux/vmalloc.h>
 #include <linux/mempolicy.h>
 #include <linux/stop_machine.h>
+#include <linux/sort.h>
+#include <linux/pfn.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -102,6 +104,38 @@ int min_free_kbytes = 1024;
 
 unsigned long __meminitdata nr_kernel_pages;
 unsigned long __meminitdata nr_all_pages;
+static unsigned long __initdata dma_reserve;
+
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+  /*
+   * MAX_ACTIVE_REGIONS determines the maxmimum number of distinct
+   * ranges of memory (RAM) that may be registered with add_active_range().
+   * Ranges passed to add_active_range() will be merged if possible
+   * so the number of times add_active_range() can be called is
+   * related to the number of nodes and the number of holes
+   */
+  #ifdef CONFIG_MAX_ACTIVE_REGIONS
+    /* Allow an architecture to set MAX_ACTIVE_REGIONS to save memory */
+    #define MAX_ACTIVE_REGIONS CONFIG_MAX_ACTIVE_REGIONS
+  #else
+    #if MAX_NUMNODES >= 32
+      /* If there can be many nodes, allow up to 50 holes per node */
+      #define MAX_ACTIVE_REGIONS (MAX_NUMNODES*50)
+    #else
+      /* By default, allow up to 256 distinct regions */
+      #define MAX_ACTIVE_REGIONS 256
+    #endif
+  #endif
+
+  struct node_active_region __initdata early_node_map[MAX_ACTIVE_REGIONS];
+  int __initdata nr_nodemap_entries;
+  unsigned long __initdata arch_zone_lowest_possible_pfn[MAX_NR_ZONES];
+  unsigned long __initdata arch_zone_highest_possible_pfn[MAX_NR_ZONES];
+#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
+  unsigned long __initdata node_boundary_start_pfn[MAX_NUMNODES];
+  unsigned long __initdata node_boundary_end_pfn[MAX_NUMNODES];
+#endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
+#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
 
 #ifdef CONFIG_DEBUG_VM
 static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
@@ -908,7 +942,7 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order,
         */
        do {
                zone = *z;
-               if (unlikely((gfp_mask & __GFP_THISNODE) &&
+               if (unlikely(NUMA_BUILD && (gfp_mask & __GFP_THISNODE) &&
                        zone->zone_pgdat != zonelist->zones[0]->zone_pgdat))
                                break;
                if ((alloc_flags & ALLOC_CPUSET) &&
@@ -1222,14 +1256,12 @@ unsigned int nr_free_pagecache_pages(void)
 {
        return nr_free_zone_pages(gfp_zone(GFP_HIGHUSER));
 }
-#ifdef CONFIG_NUMA
-static void show_node(struct zone *zone)
+
+static inline void show_node(struct zone *zone)
 {
-       printk("Node %ld ", zone_to_nid(zone));
+       if (NUMA_BUILD)
+               printk("Node %ld ", zone_to_nid(zone));
 }
-#else
-#define show_node(zone)        do { } while (0)
-#endif
 
 void si_meminfo(struct sysinfo *val)
 {
@@ -1271,34 +1303,30 @@ void si_meminfo_node(struct sysinfo *val, int nid)
  */
 void show_free_areas(void)
 {
-       int cpu, temperature;
+       int cpu;
        unsigned long active;
        unsigned long inactive;
        unsigned long free;
        struct zone *zone;
 
        for_each_zone(zone) {
-               show_node(zone);
-               printk("%s per-cpu:", zone->name);
-
-               if (!populated_zone(zone)) {
-                       printk(" empty\n");
+               if (!populated_zone(zone))
                        continue;
-               } else
-                       printk("\n");
+
+               show_node(zone);
+               printk("%s per-cpu:\n", zone->name);
 
                for_each_online_cpu(cpu) {
                        struct per_cpu_pageset *pageset;
 
                        pageset = zone_pcp(zone, cpu);
 
-                       for (temperature = 0; temperature < 2; temperature++)
-                               printk("cpu %d %s: high %d, batch %d used:%d\n",
-                                       cpu,
-                                       temperature ? "cold" : "hot",
-                                       pageset->pcp[temperature].high,
-                                       pageset->pcp[temperature].batch,
-                                       pageset->pcp[temperature].count);
+                       printk("CPU %4d: Hot: hi:%5d, btch:%4d usd:%4d   "
+                              "Cold: hi:%5d, btch:%4d usd:%4d\n",
+                              cpu, pageset->pcp[0].high,
+                              pageset->pcp[0].batch, pageset->pcp[0].count,
+                              pageset->pcp[1].high, pageset->pcp[1].batch,
+                              pageset->pcp[1].count);
                }
        }
 
@@ -1320,6 +1348,9 @@ void show_free_areas(void)
        for_each_zone(zone) {
                int i;
 
+               if (!populated_zone(zone))
+                       continue;
+
                show_node(zone);
                printk("%s"
                        " free:%lukB"
@@ -1352,12 +1383,11 @@ void show_free_areas(void)
        for_each_zone(zone) {
                unsigned long nr[MAX_ORDER], flags, order, total = 0;
 
+               if (!populated_zone(zone))
+                       continue;
+
                show_node(zone);
                printk("%s: ", zone->name);
-               if (!populated_zone(zone)) {
-                       printk("empty\n");
-                       continue;
-               }
 
                spin_lock_irqsave(&zone->lock, flags);
                for (order = 0; order < MAX_ORDER; order++) {
@@ -1561,7 +1591,7 @@ static int __meminit __build_all_zonelists(void *dummy)
 void __meminit build_all_zonelists(void)
 {
        if (system_state == SYSTEM_BOOTING) {
-               __build_all_zonelists(0);
+               __build_all_zonelists(NULL);
                cpuset_init_current_mems_allowed();
        } else {
                /* we have to stop all cpus to guaranntee there is no user
@@ -1642,25 +1672,6 @@ static inline unsigned long wait_table_bits(unsigned long size)
 
 #define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
 
-static void __init calculate_zone_totalpages(struct pglist_data *pgdat,
-               unsigned long *zones_size, unsigned long *zholes_size)
-{
-       unsigned long realtotalpages, totalpages = 0;
-       enum zone_type i;
-
-       for (i = 0; i < MAX_NR_ZONES; i++)
-               totalpages += zones_size[i];
-       pgdat->node_spanned_pages = totalpages;
-
-       realtotalpages = totalpages;
-       if (zholes_size)
-               for (i = 0; i < MAX_NR_ZONES; i++)
-                       realtotalpages -= zholes_size[i];
-       pgdat->node_present_pages = realtotalpages;
-       printk(KERN_DEBUG "On node %d totalpages: %lu\n", pgdat->node_id, realtotalpages);
-}
-
-
 /*
  * Initially all pages are reserved - free ones are freed
  * up by free_all_bootmem() once the early boot process is
@@ -1818,6 +1829,9 @@ static int __cpuinit process_zones(int cpu)
 
        for_each_zone(zone) {
 
+               if (!populated_zone(zone))
+                       continue;
+
                zone_pcp(zone, cpu) = kmalloc_node(sizeof(struct per_cpu_pageset),
                                         GFP_KERNEL, cpu_to_node(cpu));
                if (!zone_pcp(zone, cpu))
@@ -1977,6 +1991,366 @@ __meminit int init_currently_empty_zone(struct zone *zone,
        return 0;
 }
 
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+/*
+ * Basic iterator support. Return the first range of PFNs for a node
+ * Note: nid == MAX_NUMNODES returns first region regardless of node
+ */
+static int __init first_active_region_index_in_nid(int nid)
+{
+       int i;
+
+       for (i = 0; i < nr_nodemap_entries; i++)
+               if (nid == MAX_NUMNODES || early_node_map[i].nid == nid)
+                       return i;
+
+       return -1;
+}
+
+/*
+ * Basic iterator support. Return the next active range of PFNs for a node
+ * Note: nid == MAX_NUMNODES returns next region regardles of node
+ */
+static int __init next_active_region_index_in_nid(int index, int nid)
+{
+       for (index = index + 1; index < nr_nodemap_entries; index++)
+               if (nid == MAX_NUMNODES || early_node_map[index].nid == nid)
+                       return index;
+
+       return -1;
+}
+
+#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+/*
+ * Required by SPARSEMEM. Given a PFN, return what node the PFN is on.
+ * Architectures may implement their own version but if add_active_range()
+ * was used and there are no special requirements, this is a convenient
+ * alternative
+ */
+int __init early_pfn_to_nid(unsigned long pfn)
+{
+       int i;
+
+       for (i = 0; i < nr_nodemap_entries; i++) {
+               unsigned long start_pfn = early_node_map[i].start_pfn;
+               unsigned long end_pfn = early_node_map[i].end_pfn;
+
+               if (start_pfn <= pfn && pfn < end_pfn)
+                       return early_node_map[i].nid;
+       }
+
+       return 0;
+}
+#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+
+/* Basic iterator support to walk early_node_map[] */
+#define for_each_active_range_index_in_nid(i, nid) \
+       for (i = first_active_region_index_in_nid(nid); i != -1; \
+                               i = next_active_region_index_in_nid(i, nid))
+
+/**
+ * free_bootmem_with_active_regions - Call free_bootmem_node for each active range
+ * @nid: The node to free memory on. If MAX_NUMNODES, all nodes are freed
+ * @max_low_pfn: The highest PFN that till be passed to free_bootmem_node
+ *
+ * If an architecture guarantees that all ranges registered with
+ * add_active_ranges() contain no holes and may be freed, this
+ * this function may be used instead of calling free_bootmem() manually.
+ */
+void __init free_bootmem_with_active_regions(int nid,
+                                               unsigned long max_low_pfn)
+{
+       int i;
+
+       for_each_active_range_index_in_nid(i, nid) {
+               unsigned long size_pages = 0;
+               unsigned long end_pfn = early_node_map[i].end_pfn;
+
+               if (early_node_map[i].start_pfn >= max_low_pfn)
+                       continue;
+
+               if (end_pfn > max_low_pfn)
+                       end_pfn = max_low_pfn;
+
+               size_pages = end_pfn - early_node_map[i].start_pfn;
+               free_bootmem_node(NODE_DATA(early_node_map[i].nid),
+                               PFN_PHYS(early_node_map[i].start_pfn),
+                               size_pages << PAGE_SHIFT);
+       }
+}
+
+/**
+ * sparse_memory_present_with_active_regions - Call memory_present for each active range
+ * @nid: The node to call memory_present for. If MAX_NUMNODES, all nodes will be used
+ *
+ * If an architecture guarantees that all ranges registered with
+ * add_active_ranges() contain no holes and may be freed, this
+ * this function may be used instead of calling memory_present() manually.
+ */
+void __init sparse_memory_present_with_active_regions(int nid)
+{
+       int i;
+
+       for_each_active_range_index_in_nid(i, nid)
+               memory_present(early_node_map[i].nid,
+                               early_node_map[i].start_pfn,
+                               early_node_map[i].end_pfn);
+}
+
+/**
+ * push_node_boundaries - Push node boundaries to at least the requested boundary
+ * @nid: The nid of the node to push the boundary for
+ * @start_pfn: The start pfn of the node
+ * @end_pfn: The end pfn of the node
+ *
+ * In reserve-based hot-add, mem_map is allocated that is unused until hotadd
+ * time. Specifically, on x86_64, SRAT will report ranges that can potentially
+ * be hotplugged even though no physical memory exists. This function allows
+ * an arch to push out the node boundaries so mem_map is allocated that can
+ * be used later.
+ */
+#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
+void __init push_node_boundaries(unsigned int nid,
+               unsigned long start_pfn, unsigned long end_pfn)
+{
+       printk(KERN_DEBUG "Entering push_node_boundaries(%u, %lu, %lu)\n",
+                       nid, start_pfn, end_pfn);
+
+       /* Initialise the boundary for this node if necessary */
+       if (node_boundary_end_pfn[nid] == 0)
+               node_boundary_start_pfn[nid] = -1UL;
+
+       /* Update the boundaries */
+       if (node_boundary_start_pfn[nid] > start_pfn)
+               node_boundary_start_pfn[nid] = start_pfn;
+       if (node_boundary_end_pfn[nid] < end_pfn)
+               node_boundary_end_pfn[nid] = end_pfn;
+}
+
+/* If necessary, push the node boundary out for reserve hotadd */
+static void __init account_node_boundary(unsigned int nid,
+               unsigned long *start_pfn, unsigned long *end_pfn)
+{
+       printk(KERN_DEBUG "Entering account_node_boundary(%u, %lu, %lu)\n",
+                       nid, *start_pfn, *end_pfn);
+
+       /* Return if boundary information has not been provided */
+       if (node_boundary_end_pfn[nid] == 0)
+               return;
+
+       /* Check the boundaries and update if necessary */
+       if (node_boundary_start_pfn[nid] < *start_pfn)
+               *start_pfn = node_boundary_start_pfn[nid];
+       if (node_boundary_end_pfn[nid] > *end_pfn)
+               *end_pfn = node_boundary_end_pfn[nid];
+}
+#else
+void __init push_node_boundaries(unsigned int nid,
+               unsigned long start_pfn, unsigned long end_pfn) {}
+
+static void __init account_node_boundary(unsigned int nid,
+               unsigned long *start_pfn, unsigned long *end_pfn) {}
+#endif
+
+
+/**
+ * get_pfn_range_for_nid - Return the start and end page frames for a node
+ * @nid: The nid to return the range for. If MAX_NUMNODES, the min and max PFN are returned
+ * @start_pfn: Passed by reference. On return, it will have the node start_pfn
+ * @end_pfn: Passed by reference. On return, it will have the node end_pfn
+ *
+ * It returns the start and end page frame of a node based on information
+ * provided by an arch calling add_active_range(). If called for a node
+ * with no available memory, a warning is printed and the start and end
+ * PFNs will be 0
+ */
+void __init get_pfn_range_for_nid(unsigned int nid,
+                       unsigned long *start_pfn, unsigned long *end_pfn)
+{
+       int i;
+       *start_pfn = -1UL;
+       *end_pfn = 0;
+
+       for_each_active_range_index_in_nid(i, nid) {
+               *start_pfn = min(*start_pfn, early_node_map[i].start_pfn);
+               *end_pfn = max(*end_pfn, early_node_map[i].end_pfn);
+       }
+
+       if (*start_pfn == -1UL) {
+               printk(KERN_WARNING "Node %u active with no memory\n", nid);
+               *start_pfn = 0;
+       }
+
+       /* Push the node boundaries out if requested */
+       account_node_boundary(nid, start_pfn, end_pfn);
+}
+
+/*
+ * Return the number of pages a zone spans in a node, including holes
+ * present_pages = zone_spanned_pages_in_node() - zone_absent_pages_in_node()
+ */
+unsigned long __init zone_spanned_pages_in_node(int nid,
+                                       unsigned long zone_type,
+                                       unsigned long *ignored)
+{
+       unsigned long node_start_pfn, node_end_pfn;
+       unsigned long zone_start_pfn, zone_end_pfn;
+
+       /* Get the start and end of the node and zone */
+       get_pfn_range_for_nid(nid, &node_start_pfn, &node_end_pfn);
+       zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
+       zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
+
+       /* Check that this node has pages within the zone's required range */
+       if (zone_end_pfn < node_start_pfn || zone_start_pfn > node_end_pfn)
+               return 0;
+
+       /* Move the zone boundaries inside the node if necessary */
+       zone_end_pfn = min(zone_end_pfn, node_end_pfn);
+       zone_start_pfn = max(zone_start_pfn, node_start_pfn);
+
+       /* Return the spanned pages */
+       return zone_end_pfn - zone_start_pfn;
+}
+
+/*
+ * Return the number of holes in a range on a node. If nid is MAX_NUMNODES,
+ * then all holes in the requested range will be accounted for
+ */
+unsigned long __init __absent_pages_in_range(int nid,
+                               unsigned long range_start_pfn,
+                               unsigned long range_end_pfn)
+{
+       int i = 0;
+       unsigned long prev_end_pfn = 0, hole_pages = 0;
+       unsigned long start_pfn;
+
+       /* Find the end_pfn of the first active range of pfns in the node */
+       i = first_active_region_index_in_nid(nid);
+       if (i == -1)
+               return 0;
+
+       /* Account for ranges before physical memory on this node */
+       if (early_node_map[i].start_pfn > range_start_pfn)
+               hole_pages = early_node_map[i].start_pfn - range_start_pfn;
+
+       prev_end_pfn = early_node_map[i].start_pfn;
+
+       /* Find all holes for the zone within the node */
+       for (; i != -1; i = next_active_region_index_in_nid(i, nid)) {
+
+               /* No need to continue if prev_end_pfn is outside the zone */
+               if (prev_end_pfn >= range_end_pfn)
+                       break;
+
+               /* Make sure the end of the zone is not within the hole */
+               start_pfn = min(early_node_map[i].start_pfn, range_end_pfn);
+               prev_end_pfn = max(prev_end_pfn, range_start_pfn);
+
+               /* Update the hole size cound and move on */
+               if (start_pfn > range_start_pfn) {
+                       BUG_ON(prev_end_pfn > start_pfn);
+                       hole_pages += start_pfn - prev_end_pfn;
+               }
+               prev_end_pfn = early_node_map[i].end_pfn;
+       }
+
+       /* Account for ranges past physical memory on this node */
+       if (range_end_pfn > prev_end_pfn)
+               hole_pages = range_end_pfn -
+                               max(range_start_pfn, prev_end_pfn);
+
+       return hole_pages;
+}
+
+/**
+ * absent_pages_in_range - Return number of page frames in holes within a range
+ * @start_pfn: The start PFN to start searching for holes
+ * @end_pfn: The end PFN to stop searching for holes
+ *
+ * It returns the number of pages frames in memory holes within a range
+ */
+unsigned long __init absent_pages_in_range(unsigned long start_pfn,
+                                                       unsigned long end_pfn)
+{
+       return __absent_pages_in_range(MAX_NUMNODES, start_pfn, end_pfn);
+}
+
+/* Return the number of page frames in holes in a zone on a node */
+unsigned long __init zone_absent_pages_in_node(int nid,
+                                       unsigned long zone_type,
+                                       unsigned long *ignored)
+{
+       unsigned long node_start_pfn, node_end_pfn;
+       unsigned long zone_start_pfn, zone_end_pfn;
+
+       get_pfn_range_for_nid(nid, &node_start_pfn, &node_end_pfn);
+       zone_start_pfn = max(arch_zone_lowest_possible_pfn[zone_type],
+                                                       node_start_pfn);
+       zone_end_pfn = min(arch_zone_highest_possible_pfn[zone_type],
+                                                       node_end_pfn);
+
+       return __absent_pages_in_range(nid, zone_start_pfn, zone_end_pfn);
+}
+
+/* Return the zone index a PFN is in */
+int memmap_zone_idx(struct page *lmem_map)
+{
+       int i;
+       unsigned long phys_addr = virt_to_phys(lmem_map);
+       unsigned long pfn = phys_addr >> PAGE_SHIFT;
+
+       for (i = 0; i < MAX_NR_ZONES; i++)
+               if (pfn < arch_zone_highest_possible_pfn[i])
+                       break;
+
+       return i;
+}
+#else
+static inline unsigned long zone_spanned_pages_in_node(int nid,
+                                       unsigned long zone_type,
+                                       unsigned long *zones_size)
+{
+       return zones_size[zone_type];
+}
+
+static inline unsigned long zone_absent_pages_in_node(int nid,
+                                               unsigned long zone_type,
+                                               unsigned long *zholes_size)
+{
+       if (!zholes_size)
+               return 0;
+
+       return zholes_size[zone_type];
+}
+
+static inline int memmap_zone_idx(struct page *lmem_map)
+{
+       return MAX_NR_ZONES;
+}
+#endif
+
+static void __init calculate_node_totalpages(struct pglist_data *pgdat,
+               unsigned long *zones_size, unsigned long *zholes_size)
+{
+       unsigned long realtotalpages, totalpages = 0;
+       enum zone_type i;
+
+       for (i = 0; i < MAX_NR_ZONES; i++)
+               totalpages += zone_spanned_pages_in_node(pgdat->node_id, i,
+                                                               zones_size);
+       pgdat->node_spanned_pages = totalpages;
+
+       realtotalpages = totalpages;
+       for (i = 0; i < MAX_NR_ZONES; i++)
+               realtotalpages -=
+                       zone_absent_pages_in_node(pgdat->node_id, i,
+                                                               zholes_size);
+       pgdat->node_present_pages = realtotalpages;
+       printk(KERN_DEBUG "On node %d totalpages: %lu\n", pgdat->node_id,
+                                                       realtotalpages);
+}
+
 /*
  * Set up the zone data structures:
  *   - mark all pages reserved
@@ -1998,11 +2372,34 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat,
        
        for (j = 0; j < MAX_NR_ZONES; j++) {
                struct zone *zone = pgdat->node_zones + j;
-               unsigned long size, realsize;
+               unsigned long size, realsize, memmap_pages;
 
-               realsize = size = zones_size[j];
-               if (zholes_size)
-                       realsize -= zholes_size[j];
+               size = zone_spanned_pages_in_node(nid, j, zones_size);
+               realsize = size - zone_absent_pages_in_node(nid, j,
+                                                               zholes_size);
+
+               /*
+                * Adjust realsize so that it accounts for how much memory
+                * is used by this zone for memmap. This affects the watermark
+                * and per-cpu initialisations
+                */
+               memmap_pages = (size * sizeof(struct page)) >> PAGE_SHIFT;
+               if (realsize >= memmap_pages) {
+                       realsize -= memmap_pages;
+                       printk(KERN_DEBUG
+                               "  %s zone: %lu pages used for memmap\n",
+                               zone_names[j], memmap_pages);
+               } else
+                       printk(KERN_WARNING
+                               "  %s zone: %lu pages exceeds realsize %lu\n",
+                               zone_names[j], memmap_pages, realsize);
+
+               /* Account for reserved DMA pages */
+               if (j == ZONE_DMA && realsize > dma_reserve) {
+                       realsize -= dma_reserve;
+                       printk(KERN_DEBUG "  DMA zone: %lu pages reserved\n",
+                                                               dma_reserve);
+               }
 
                if (!is_highmem_idx(j))
                        nr_kernel_pages += realsize;
@@ -2011,6 +2408,7 @@ static void __meminit free_area_init_core(struct pglist_data *pgdat,
                zone->spanned_pages = size;
                zone->present_pages = realsize;
 #ifdef CONFIG_NUMA
+               zone->node = nid;
                zone->min_unmapped_pages = (realsize*sysctl_min_unmapped_ratio)
                                                / 100;
                zone->min_slab_pages = (realsize * sysctl_min_slab_ratio) / 100;
@@ -2073,8 +2471,13 @@ static void __init alloc_node_mem_map(struct pglist_data *pgdat)
        /*
         * With no DISCONTIG, the global mem_map is just set as node 0's
         */
-       if (pgdat == NODE_DATA(0))
+       if (pgdat == NODE_DATA(0)) {
                mem_map = NODE_DATA(0)->node_mem_map;
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+               if (page_to_pfn(mem_map) != pgdat->node_start_pfn)
+                       mem_map -= pgdat->node_start_pfn;
+#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
+       }
 #endif
 #endif /* CONFIG_FLAT_NODE_MEM_MAP */
 }
@@ -2085,13 +2488,255 @@ void __meminit free_area_init_node(int nid, struct pglist_data *pgdat,
 {
        pgdat->node_id = nid;
        pgdat->node_start_pfn = node_start_pfn;
-       calculate_zone_totalpages(pgdat, zones_size, zholes_size);
+       calculate_node_totalpages(pgdat, zones_size, zholes_size);
 
        alloc_node_mem_map(pgdat);
 
        free_area_init_core(pgdat, zones_size, zholes_size);
 }
 
+#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
+/**
+ * add_active_range - Register a range of PFNs backed by physical memory
+ * @nid: The node ID the range resides on
+ * @start_pfn: The start PFN of the available physical memory
+ * @end_pfn: The end PFN of the available physical memory
+ *
+ * These ranges are stored in an early_node_map[] and later used by
+ * free_area_init_nodes() to calculate zone sizes and holes. If the
+ * range spans a memory hole, it is up to the architecture to ensure
+ * the memory is not freed by the bootmem allocator. If possible
+ * the range being registered will be merged with existing ranges.
+ */
+void __init add_active_range(unsigned int nid, unsigned long start_pfn,
+                                               unsigned long end_pfn)
+{
+       int i;
+
+       printk(KERN_DEBUG "Entering add_active_range(%d, %lu, %lu) "
+                         "%d entries of %d used\n",
+                         nid, start_pfn, end_pfn,
+                         nr_nodemap_entries, MAX_ACTIVE_REGIONS);
+
+       /* Merge with existing active regions if possible */
+       for (i = 0; i < nr_nodemap_entries; i++) {
+               if (early_node_map[i].nid != nid)
+                       continue;
+
+               /* Skip if an existing region covers this new one */
+               if (start_pfn >= early_node_map[i].start_pfn &&
+                               end_pfn <= early_node_map[i].end_pfn)
+                       return;
+
+               /* Merge forward if suitable */
+               if (start_pfn <= early_node_map[i].end_pfn &&
+                               end_pfn > early_node_map[i].end_pfn) {
+                       early_node_map[i].end_pfn = end_pfn;
+                       return;
+               }
+
+               /* Merge backward if suitable */
+               if (start_pfn < early_node_map[i].end_pfn &&
+                               end_pfn >= early_node_map[i].start_pfn) {
+                       early_node_map[i].start_pfn = start_pfn;
+                       return;
+               }
+       }
+
+       /* Check that early_node_map is large enough */
+       if (i >= MAX_ACTIVE_REGIONS) {
+               printk(KERN_CRIT "More than %d memory regions, truncating\n",
+                                                       MAX_ACTIVE_REGIONS);
+               return;
+       }
+
+       early_node_map[i].nid = nid;
+       early_node_map[i].start_pfn = start_pfn;
+       early_node_map[i].end_pfn = end_pfn;
+       nr_nodemap_entries = i + 1;
+}
+
+/**
+ * shrink_active_range - Shrink an existing registered range of PFNs
+ * @nid: The node id the range is on that should be shrunk
+ * @old_end_pfn: The old end PFN of the range
+ * @new_end_pfn: The new PFN of the range
+ *
+ * i386 with NUMA use alloc_remap() to store a node_mem_map on a local node.
+ * The map is kept at the end physical page range that has already been
+ * registered with add_active_range(). This function allows an arch to shrink
+ * an existing registered range.
+ */
+void __init shrink_active_range(unsigned int nid, unsigned long old_end_pfn,
+                                               unsigned long new_end_pfn)
+{
+       int i;
+
+       /* Find the old active region end and shrink */
+       for_each_active_range_index_in_nid(i, nid)
+               if (early_node_map[i].end_pfn == old_end_pfn) {
+                       early_node_map[i].end_pfn = new_end_pfn;
+                       break;
+               }
+}
+
+/**
+ * remove_all_active_ranges - Remove all currently registered regions
+ * During discovery, it may be found that a table like SRAT is invalid
+ * and an alternative discovery method must be used. This function removes
+ * all currently registered regions.
+ */
+void __init remove_all_active_ranges()
+{
+       memset(early_node_map, 0, sizeof(early_node_map));
+       nr_nodemap_entries = 0;
+#ifdef CONFIG_MEMORY_HOTPLUG_RESERVE
+       memset(node_boundary_start_pfn, 0, sizeof(node_boundary_start_pfn));
+       memset(node_boundary_end_pfn, 0, sizeof(node_boundary_end_pfn));
+#endif /* CONFIG_MEMORY_HOTPLUG_RESERVE */
+}
+
+/* Compare two active node_active_regions */
+static int __init cmp_node_active_region(const void *a, const void *b)
+{
+       struct node_active_region *arange = (struct node_active_region *)a;
+       struct node_active_region *brange = (struct node_active_region *)b;
+
+       /* Done this way to avoid overflows */
+       if (arange->start_pfn > brange->start_pfn)
+               return 1;
+       if (arange->start_pfn < brange->start_pfn)
+               return -1;
+
+       return 0;
+}
+
+/* sort the node_map by start_pfn */
+static void __init sort_node_map(void)
+{
+       sort(early_node_map, (size_t)nr_nodemap_entries,
+                       sizeof(struct node_active_region),
+                       cmp_node_active_region, NULL);
+}
+
+/* Find the lowest pfn for a node. This depends on a sorted early_node_map */
+unsigned long __init find_min_pfn_for_node(unsigned long nid)
+{
+       int i;
+
+       /* Assuming a sorted map, the first range found has the starting pfn */
+       for_each_active_range_index_in_nid(i, nid)
+               return early_node_map[i].start_pfn;
+
+       printk(KERN_WARNING "Could not find start_pfn for node %lu\n", nid);
+       return 0;
+}
+
+/**
+ * find_min_pfn_with_active_regions - Find the minimum PFN registered
+ *
+ * It returns the minimum PFN based on information provided via
+ * add_active_range()
+ */
+unsigned long __init find_min_pfn_with_active_regions(void)
+{
+       return find_min_pfn_for_node(MAX_NUMNODES);
+}
+
+/**
+ * find_max_pfn_with_active_regions - Find the maximum PFN registered
+ *
+ * It returns the maximum PFN based on information provided via
+ * add_active_range()
+ */
+unsigned long __init find_max_pfn_with_active_regions(void)
+{
+       int i;
+       unsigned long max_pfn = 0;
+
+       for (i = 0; i < nr_nodemap_entries; i++)
+               max_pfn = max(max_pfn, early_node_map[i].end_pfn);
+
+       return max_pfn;
+}
+
+/**
+ * free_area_init_nodes - Initialise all pg_data_t and zone data
+ * @arch_max_dma_pfn: The maximum PFN usable for ZONE_DMA
+ * @arch_max_dma32_pfn: The maximum PFN usable for ZONE_DMA32
+ * @arch_max_low_pfn: The maximum PFN usable for ZONE_NORMAL
+ * @arch_max_high_pfn: The maximum PFN usable for ZONE_HIGHMEM
+ *
+ * This will call free_area_init_node() for each active node in the system.
+ * Using the page ranges provided by add_active_range(), the size of each
+ * zone in each node and their holes is calculated. If the maximum PFN
+ * between two adjacent zones match, it is assumed that the zone is empty.
+ * For example, if arch_max_dma_pfn == arch_max_dma32_pfn, it is assumed
+ * that arch_max_dma32_pfn has no pages. It is also assumed that a zone
+ * starts where the previous one ended. For example, ZONE_DMA32 starts
+ * at arch_max_dma_pfn.
+ */
+void __init free_area_init_nodes(unsigned long *max_zone_pfn)
+{
+       unsigned long nid;
+       enum zone_type i;
+
+       /* Record where the zone boundaries are */
+       memset(arch_zone_lowest_possible_pfn, 0,
+                               sizeof(arch_zone_lowest_possible_pfn));
+       memset(arch_zone_highest_possible_pfn, 0,
+                               sizeof(arch_zone_highest_possible_pfn));
+       arch_zone_lowest_possible_pfn[0] = find_min_pfn_with_active_regions();
+       arch_zone_highest_possible_pfn[0] = max_zone_pfn[0];
+       for (i = 1; i < MAX_NR_ZONES; i++) {
+               arch_zone_lowest_possible_pfn[i] =
+                       arch_zone_highest_possible_pfn[i-1];
+               arch_zone_highest_possible_pfn[i] =
+                       max(max_zone_pfn[i], arch_zone_lowest_possible_pfn[i]);
+       }
+
+       /* Regions in the early_node_map can be in any order */
+       sort_node_map();
+
+       /* Print out the zone ranges */
+       printk("Zone PFN ranges:\n");
+       for (i = 0; i < MAX_NR_ZONES; i++)
+               printk("  %-8s %8lu -> %8lu\n",
+                               zone_names[i],
+                               arch_zone_lowest_possible_pfn[i],
+                               arch_zone_highest_possible_pfn[i]);
+
+       /* Print out the early_node_map[] */
+       printk("early_node_map[%d] active PFN ranges\n", nr_nodemap_entries);
+       for (i = 0; i < nr_nodemap_entries; i++)
+               printk("  %3d: %8lu -> %8lu\n", early_node_map[i].nid,
+                                               early_node_map[i].start_pfn,
+                                               early_node_map[i].end_pfn);
+
+       /* Initialise every node */
+       for_each_online_node(nid) {
+               pg_data_t *pgdat = NODE_DATA(nid);
+               free_area_init_node(nid, pgdat, NULL,
+                               find_min_pfn_for_node(nid), NULL);
+       }
+}
+#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
+
+/**
+ * set_dma_reserve - Account the specified number of pages reserved in ZONE_DMA
+ * @new_dma_reserve - The number of pages to mark reserved
+ *
+ * The per-cpu batchsize and zone watermarks are determined by present_pages.
+ * In the DMA zone, a significant percentage may be consumed by kernel image
+ * and other unfreeable allocations which can skew the watermarks badly. This
+ * function may optionally be used to account for unfreeable pages in
+ * ZONE_DMA. The effect will be lower watermarks and smaller per-cpu batchsize
+ */
+void __init set_dma_reserve(unsigned long new_dma_reserve)
+{
+       dma_reserve = new_dma_reserve;
+}
+
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 static bootmem_data_t contig_bootmem_data;
 struct pglist_data contig_page_data = { .bdata = &contig_bootmem_data };
index 8631be45b40d46304d0dcbc1f398acaf1325beaf..eda907c3a86aa14399e8a30aab95ec8dc8cff88c 100644 (file)
@@ -1351,7 +1351,6 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
                inode->i_mode = mode;
                inode->i_uid = current->fsuid;
                inode->i_gid = current->fsgid;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_mapping->a_ops = &shmem_aops;
                inode->i_mapping->backing_dev_info = &shmem_backing_dev_info;
@@ -2157,8 +2156,7 @@ static int init_inodecache(void)
 
 static void destroy_inodecache(void)
 {
-       if (kmem_cache_destroy(shmem_inode_cachep))
-               printk(KERN_INFO "shmem_inode_cache: not all structures were freed\n");
+       kmem_cache_destroy(shmem_inode_cachep);
 }
 
 static const struct address_space_operations shmem_aops = {
index 7a48eb1a60c834bf3a3b9698f43a82d8ebcae1e8..792bfe320a8b2c0896f8568f8d07de40203f8cf2 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -972,7 +972,39 @@ static int transfer_objects(struct array_cache *to,
        return nr;
 }
 
-#ifdef CONFIG_NUMA
+#ifndef CONFIG_NUMA
+
+#define drain_alien_cache(cachep, alien) do { } while (0)
+#define reap_alien(cachep, l3) do { } while (0)
+
+static inline struct array_cache **alloc_alien_cache(int node, int limit)
+{
+       return (struct array_cache **)BAD_ALIEN_MAGIC;
+}
+
+static inline void free_alien_cache(struct array_cache **ac_ptr)
+{
+}
+
+static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
+{
+       return 0;
+}
+
+static inline void *alternate_node_alloc(struct kmem_cache *cachep,
+               gfp_t flags)
+{
+       return NULL;
+}
+
+static inline void *__cache_alloc_node(struct kmem_cache *cachep,
+                gfp_t flags, int nodeid)
+{
+       return NULL;
+}
+
+#else  /* CONFIG_NUMA */
+
 static void *__cache_alloc_node(struct kmem_cache *, gfp_t, int);
 static void *alternate_node_alloc(struct kmem_cache *, gfp_t);
 
@@ -1101,26 +1133,6 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
        }
        return 1;
 }
-
-#else
-
-#define drain_alien_cache(cachep, alien) do { } while (0)
-#define reap_alien(cachep, l3) do { } while (0)
-
-static inline struct array_cache **alloc_alien_cache(int node, int limit)
-{
-       return (struct array_cache **)BAD_ALIEN_MAGIC;
-}
-
-static inline void free_alien_cache(struct array_cache **ac_ptr)
-{
-}
-
-static inline int cache_free_alien(struct kmem_cache *cachep, void *objp)
-{
-       return 0;
-}
-
 #endif
 
 static int __cpuinit cpuup_callback(struct notifier_block *nfb,
@@ -1564,7 +1576,13 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid)
         */
        flags |= __GFP_COMP;
 #endif
-       flags |= cachep->gfpflags;
+
+       /*
+        * Under NUMA we want memory on the indicated node. We will handle
+        * the needed fallback ourselves since we want to serve from our
+        * per node object lists first for other nodes.
+        */
+       flags |= cachep->gfpflags | GFP_THISNODE;
 
        page = alloc_pages_node(nodeid, flags, cachep->gfporder);
        if (!page)
@@ -2442,7 +2460,6 @@ EXPORT_SYMBOL(kmem_cache_shrink);
  * @cachep: the cache to destroy
  *
  * Remove a struct kmem_cache object from the slab cache.
- * Returns 0 on success.
  *
  * It is expected this function will be called by a module when it is
  * unloaded.  This will remove the cache completely, and avoid a duplicate
@@ -2454,7 +2471,7 @@ EXPORT_SYMBOL(kmem_cache_shrink);
  * The caller must guarantee that noone will allocate memory from the cache
  * during the kmem_cache_destroy().
  */
-int kmem_cache_destroy(struct kmem_cache *cachep)
+void kmem_cache_destroy(struct kmem_cache *cachep)
 {
        BUG_ON(!cachep || in_interrupt());
 
@@ -2475,7 +2492,7 @@ int kmem_cache_destroy(struct kmem_cache *cachep)
                list_add(&cachep->next, &cache_chain);
                mutex_unlock(&cache_chain_mutex);
                unlock_cpu_hotplug();
-               return 1;
+               return;
        }
 
        if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
@@ -2483,7 +2500,6 @@ int kmem_cache_destroy(struct kmem_cache *cachep)
 
        __kmem_cache_destroy(cachep);
        unlock_cpu_hotplug();
-       return 0;
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
@@ -3030,14 +3046,6 @@ static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
        void *objp;
        struct array_cache *ac;
 
-#ifdef CONFIG_NUMA
-       if (unlikely(current->flags & (PF_SPREAD_SLAB | PF_MEMPOLICY))) {
-               objp = alternate_node_alloc(cachep, flags);
-               if (objp != NULL)
-                       return objp;
-       }
-#endif
-
        check_irq_off();
        ac = cpu_cache_get(cachep);
        if (likely(ac->avail)) {
@@ -3055,12 +3063,24 @@ static __always_inline void *__cache_alloc(struct kmem_cache *cachep,
                                                gfp_t flags, void *caller)
 {
        unsigned long save_flags;
-       void *objp;
+       void *objp = NULL;
 
        cache_alloc_debugcheck_before(cachep, flags);
 
        local_irq_save(save_flags);
-       objp = ____cache_alloc(cachep, flags);
+
+       if (unlikely(NUMA_BUILD &&
+                       current->flags & (PF_SPREAD_SLAB | PF_MEMPOLICY)))
+               objp = alternate_node_alloc(cachep, flags);
+
+       if (!objp)
+               objp = ____cache_alloc(cachep, flags);
+       /*
+        * We may just have run out of memory on the local node.
+        * __cache_alloc_node() knows how to locate memory on other nodes
+        */
+       if (NUMA_BUILD && !objp)
+               objp = __cache_alloc_node(cachep, flags, numa_node_id());
        local_irq_restore(save_flags);
        objp = cache_alloc_debugcheck_after(cachep, flags, objp,
                                            caller);
@@ -3079,7 +3099,7 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
        int nid_alloc, nid_here;
 
-       if (in_interrupt())
+       if (in_interrupt() || (flags & __GFP_THISNODE))
                return NULL;
        nid_alloc = nid_here = numa_node_id();
        if (cpuset_do_slab_mem_spread() && (cachep->flags & SLAB_MEM_SPREAD))
@@ -3091,6 +3111,28 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags)
        return NULL;
 }
 
+/*
+ * Fallback function if there was no memory available and no objects on a
+ * certain node and we are allowed to fall back. We mimick the behavior of
+ * the page allocator. We fall back according to a zonelist determined by
+ * the policy layer while obeying cpuset constraints.
+ */
+void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
+{
+       struct zonelist *zonelist = &NODE_DATA(slab_node(current->mempolicy))
+                                       ->node_zonelists[gfp_zone(flags)];
+       struct zone **z;
+       void *obj = NULL;
+
+       for (z = zonelist->zones; *z && !obj; z++)
+               if (zone_idx(*z) <= ZONE_NORMAL &&
+                               cpuset_zone_allowed(*z, flags))
+                       obj = __cache_alloc_node(cache,
+                                       flags | __GFP_THISNODE,
+                                       zone_to_nid(*z));
+       return obj;
+}
+
 /*
  * A interface to enable slab creation on nodeid
  */
@@ -3144,11 +3186,15 @@ retry:
 must_grow:
        spin_unlock(&l3->list_lock);
        x = cache_grow(cachep, flags, nodeid);
+       if (x)
+               goto retry;
 
-       if (!x)
-               return NULL;
+       if (!(flags & __GFP_THISNODE))
+               /* Unable to grow the cache. Fall back to other nodes. */
+               return fallback_alloc(cachep, flags);
+
+       return NULL;
 
-       goto retry;
 done:
        return obj;
 }
index 20188627347c5dae1ae2575e1f036b6d9b03906f..542394184a58e6c825a3b24cc7dfe1ad0e6e4fba 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -270,10 +270,9 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
 }
 EXPORT_SYMBOL(kmem_cache_create);
 
-int kmem_cache_destroy(struct kmem_cache *c)
+void kmem_cache_destroy(struct kmem_cache *c)
 {
        slob_free(c, sizeof(struct kmem_cache));
-       return 0;
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
index c6ab55ec6883378cb46367e54c7568f1f2b3983d..a654928323dcc4459cf33b59f67be5868d5b105d 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/swap.h>
 #include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/pagevec.h>
@@ -52,36 +53,26 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
 /*
  * This is for invalidate_inode_pages().  That function can be called at
  * any time, and is not supposed to throw away dirty pages.  But pages can
- * be marked dirty at any time too.  So we re-check the dirtiness inside
- * ->tree_lock.  That provides exclusion against the __set_page_dirty
- * functions.
+ * be marked dirty at any time too, so use remove_mapping which safely
+ * discards clean, unused pages.
  *
  * Returns non-zero if the page was successfully invalidated.
  */
 static int
 invalidate_complete_page(struct address_space *mapping, struct page *page)
 {
+       int ret;
+
        if (page->mapping != mapping)
                return 0;
 
        if (PagePrivate(page) && !try_to_release_page(page, 0))
                return 0;
 
-       write_lock_irq(&mapping->tree_lock);
-       if (PageDirty(page))
-               goto failed;
-       if (page_count(page) != 2)      /* caller's ref + pagecache ref */
-               goto failed;
-
-       BUG_ON(PagePrivate(page));
-       __remove_from_page_cache(page);
-       write_unlock_irq(&mapping->tree_lock);
+       ret = remove_mapping(mapping, page);
        ClearPageUptodate(page);
-       page_cache_release(page);       /* pagecache ref */
-       return 1;
-failed:
-       write_unlock_irq(&mapping->tree_lock);
-       return 0;
+
+       return ret;
 }
 
 /**
index 9aad8b0cc6ee71f5da612d0c4bd79aa8a3fb4476..1ac191ce564142b46cf46ec7655231d76aad093e 100644 (file)
@@ -241,7 +241,6 @@ struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
 
 /**
  *     get_vm_area  -  reserve a contingous kernel virtual area
- *
  *     @size:          size of the area
  *     @flags:         %VM_IOREMAP for I/O mappings or VM_ALLOC
  *
@@ -273,7 +272,7 @@ static struct vm_struct *__find_vm_area(void *addr)
 }
 
 /* Caller must hold vmlist_lock */
-struct vm_struct *__remove_vm_area(void *addr)
+static struct vm_struct *__remove_vm_area(void *addr)
 {
        struct vm_struct **p, *tmp;
 
@@ -296,7 +295,6 @@ found:
 
 /**
  *     remove_vm_area  -  find and remove a contingous kernel virtual area
- *
  *     @addr:          base address
  *
  *     Search for the kernel VM area starting at @addr, and remove it.
@@ -355,7 +353,6 @@ void __vunmap(void *addr, int deallocate_pages)
 
 /**
  *     vfree  -  release memory allocated by vmalloc()
- *
  *     @addr:          memory base address
  *
  *     Free the virtually contiguous memory area starting at @addr, as
@@ -373,7 +370,6 @@ EXPORT_SYMBOL(vfree);
 
 /**
  *     vunmap  -  release virtual mapping obtained by vmap()
- *
  *     @addr:          memory base address
  *
  *     Free the virtually contiguous memory area starting at @addr,
@@ -390,7 +386,6 @@ EXPORT_SYMBOL(vunmap);
 
 /**
  *     vmap  -  map an array of pages into virtually contiguous space
- *
  *     @pages:         array of page pointers
  *     @count:         number of pages to map
  *     @flags:         vm_area->flags
@@ -471,7 +466,6 @@ void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask, pgprot_t prot)
 
 /**
  *     __vmalloc_node  -  allocate virtually contiguous memory
- *
  *     @size:          allocation size
  *     @gfp_mask:      flags for the page level allocator
  *     @prot:          protection mask for the allocated pages
@@ -505,9 +499,7 @@ EXPORT_SYMBOL(__vmalloc);
 
 /**
  *     vmalloc  -  allocate virtually contiguous memory
- *
  *     @size:          allocation size
- *
  *     Allocate enough pages to cover @size from the page level
  *     allocator and map them into contiguous kernel virtual space.
  *
@@ -521,11 +513,11 @@ void *vmalloc(unsigned long size)
 EXPORT_SYMBOL(vmalloc);
 
 /**
- *     vmalloc_user  -  allocate virtually contiguous memory which has
- *                        been zeroed so it can be mapped to userspace without
- *                        leaking data.
+ * vmalloc_user - allocate zeroed virtually contiguous memory for userspace
+ * @size: allocation size
  *
- *     @size:          allocation size
+ * The resulting memory area is zeroed so it can be mapped to userspace
+ * without leaking data.
  */
 void *vmalloc_user(unsigned long size)
 {
@@ -544,7 +536,6 @@ EXPORT_SYMBOL(vmalloc_user);
 
 /**
  *     vmalloc_node  -  allocate memory on a specific node
- *
  *     @size:          allocation size
  *     @node:          numa node
  *
@@ -566,7 +557,6 @@ EXPORT_SYMBOL(vmalloc_node);
 
 /**
  *     vmalloc_exec  -  allocate virtually contiguous, executable memory
- *
  *     @size:          allocation size
  *
  *     Kernel-internal function to allocate enough pages to cover @size
@@ -584,7 +574,6 @@ void *vmalloc_exec(unsigned long size)
 
 /**
  *     vmalloc_32  -  allocate virtually contiguous memory (32bit addressable)
- *
  *     @size:          allocation size
  *
  *     Allocate enough 32bit PA addressable pages to cover @size from the
@@ -597,11 +586,11 @@ void *vmalloc_32(unsigned long size)
 EXPORT_SYMBOL(vmalloc_32);
 
 /**
- *     vmalloc_32_user  -  allocate virtually contiguous memory (32bit
- *                           addressable) which is zeroed so it can be
- *                           mapped to userspace without leaking data.
- *
+ * vmalloc_32_user - allocate zeroed virtually contiguous 32bit memory
  *     @size:          allocation size
+ *
+ * The resulting memory area is 32bit addressable and zeroed so it can be
+ * mapped to userspace without leaking data.
  */
 void *vmalloc_32_user(unsigned long size)
 {
@@ -695,7 +684,6 @@ finished:
 
 /**
  *     remap_vmalloc_range  -  map vmalloc pages to userspace
- *
  *     @vma:           vma to cover (map full range of vma)
  *     @addr:          vmalloc memory
  *     @pgoff:         number of pages into addr before first page to map
index 87779dda4ec6d7af4afe8427c6cf0476138d3245..eca70310adb26239e94c5435eaf2abf0271c89fa 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/pagemap.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
+#include <linux/vmstat.h>
 #include <linux/file.h>
 #include <linux/writeback.h>
 #include <linux/blkdev.h>
@@ -370,7 +371,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping)
                        /* synchronous write or broken a_ops? */
                        ClearPageReclaim(page);
                }
-
+               inc_zone_page_state(page, NR_VMSCAN_WRITE);
                return PAGE_SUCCESS;
        }
 
@@ -383,11 +384,30 @@ int remove_mapping(struct address_space *mapping, struct page *page)
        BUG_ON(mapping != page_mapping(page));
 
        write_lock_irq(&mapping->tree_lock);
-
        /*
-        * The non-racy check for busy page.  It is critical to check
-        * PageDirty _after_ making sure that the page is freeable and
-        * not in use by anybody.       (pagecache + us == 2)
+        * The non racy check for a busy page.
+        *
+        * Must be careful with the order of the tests. When someone has
+        * a ref to the page, it may be possible that they dirty it then
+        * drop the reference. So if PageDirty is tested before page_count
+        * here, then the following race may occur:
+        *
+        * get_user_pages(&page);
+        * [user mapping goes away]
+        * write_to(page);
+        *                              !PageDirty(page)    [good]
+        * SetPageDirty(page);
+        * put_page(page);
+        *                              !page_count(page)   [good, discard it]
+        *
+        * [oops, our write_to data is lost]
+        *
+        * Reversing the order of the tests ensures such a situation cannot
+        * escape unnoticed. The smp_rmb is needed to ensure the page->flags
+        * load is not satisfied before that of page->_count.
+        *
+        * Note that if SetPageDirty is always performed via set_page_dirty,
+        * and thus under tree_lock, then this ordering is not required.
         */
        if (unlikely(page_count(page) != 2))
                goto cannot_free;
index 490d8c1a0ded5efe731e6729136e3460341b3e5e..a2b6a9f96e5c6390625ec031763a74de9fa5f5b2 100644 (file)
@@ -371,7 +371,7 @@ void zone_statistics(struct zonelist *zonelist, struct zone *z)
                __inc_zone_state(z, NUMA_MISS);
                __inc_zone_state(zonelist->zones[0], NUMA_FOREIGN);
        }
-       if (z->zone_pgdat == NODE_DATA(numa_node_id()))
+       if (z->node == numa_node_id())
                __inc_zone_state(z, NUMA_LOCAL);
        else
                __inc_zone_state(z, NUMA_OTHER);
@@ -465,6 +465,7 @@ static char *vmstat_text[] = {
        "nr_writeback",
        "nr_unstable",
        "nr_bounce",
+       "nr_vmscan_write",
 
 #ifdef CONFIG_NUMA
        "numa_hit",
index 13472762b18b4c89f57c7bb27916bd8b67b47339..f47f319bb7dc2ae78b02e5f97f2d84519e686710 100644 (file)
@@ -344,8 +344,6 @@ static ssize_t wireless_show(struct class_device *cd, char *buf,
                if(dev->wireless_handlers &&
                   dev->wireless_handlers->get_wireless_stats)
                        iw = dev->wireless_handlers->get_wireless_stats(dev);
-               else if (dev->get_wireless_stats)
-                       iw = dev->get_wireless_stats(dev);
                if (iw != NULL)
                        ret = (*format)(iw, buf);
        }
@@ -465,8 +463,7 @@ int netdev_register_sysfs(struct net_device *net)
                *groups++ = &netstat_group;
 
 #ifdef WIRELESS_EXT
-       if (net->get_wireless_stats
-           || (net->wireless_handlers && net->wireless_handlers->get_wireless_stats))
+       if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
                *groups++ = &wireless_group;
 #endif
 
index 3168fca312f7c4d188dd9162f8b3dd43942692b3..ffff0da46c6ee2a3703a9f3116eab0162b4727e6 100644 (file)
  *
  * v8 - 17.02.06 - Jean II
  *     o RtNetlink requests support (SET/GET)
+ *
+ * v8b - 03.08.06 - Herbert Xu
+ *     o Fix Wireless Event locking issues.
+ *
+ * v9 - 14.3.06 - Jean II
+ *     o Change length in ESSID and NICK to strlen() instead of strlen()+1
+ *     o Make standard_ioctl_num and standard_event_num unsigned
+ *     o Remove (struct net_device *)->get_wireless_stats()
  */
 
 /***************************** INCLUDES *****************************/
@@ -234,24 +242,24 @@ static const struct iw_ioctl_description standard_ioctl[] = {
        [SIOCSIWESSID   - SIOCIWFIRST] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
-               .max_tokens     = IW_ESSID_MAX_SIZE + 1,
+               .max_tokens     = IW_ESSID_MAX_SIZE,
                .flags          = IW_DESCR_FLAG_EVENT,
        },
        [SIOCGIWESSID   - SIOCIWFIRST] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
-               .max_tokens     = IW_ESSID_MAX_SIZE + 1,
+               .max_tokens     = IW_ESSID_MAX_SIZE,
                .flags          = IW_DESCR_FLAG_DUMP,
        },
        [SIOCSIWNICKN   - SIOCIWFIRST] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
-               .max_tokens     = IW_ESSID_MAX_SIZE + 1,
+               .max_tokens     = IW_ESSID_MAX_SIZE,
        },
        [SIOCGIWNICKN   - SIOCIWFIRST] = {
                .header_type    = IW_HEADER_TYPE_POINT,
                .token_size     = 1,
-               .max_tokens     = IW_ESSID_MAX_SIZE + 1,
+               .max_tokens     = IW_ESSID_MAX_SIZE,
        },
        [SIOCSIWRATE    - SIOCIWFIRST] = {
                .header_type    = IW_HEADER_TYPE_PARAM,
@@ -338,8 +346,8 @@ static const struct iw_ioctl_description standard_ioctl[] = {
                .max_tokens     = sizeof(struct iw_pmksa),
        },
 };
-static const int standard_ioctl_num = (sizeof(standard_ioctl) /
-                                      sizeof(struct iw_ioctl_description));
+static const unsigned standard_ioctl_num = (sizeof(standard_ioctl) /
+                                           sizeof(struct iw_ioctl_description));
 
 /*
  * Meta-data about all the additional standard Wireless Extension events
@@ -389,8 +397,8 @@ static const struct iw_ioctl_description standard_event[] = {
                .max_tokens     = sizeof(struct iw_pmkid_cand),
        },
 };
-static const int standard_event_num = (sizeof(standard_event) /
-                                      sizeof(struct iw_ioctl_description));
+static const unsigned standard_event_num = (sizeof(standard_event) /
+                                           sizeof(struct iw_ioctl_description));
 
 /* Size (in bytes) of the various private data types */
 static const char iw_priv_type_size[] = {
@@ -465,17 +473,6 @@ static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
           (dev->wireless_handlers->get_wireless_stats != NULL))
                return dev->wireless_handlers->get_wireless_stats(dev);
 
-       /* Old location, field to be removed in next WE */
-       if(dev->get_wireless_stats) {
-               static int printed_message;
-
-               if (!printed_message++)
-                       printk(KERN_DEBUG "%s (WE) : Driver using old /proc/net/wireless support, please fix driver !\n",
-                               dev->name);
-
-               return dev->get_wireless_stats(dev);
-       }
-
        /* Not found */
        return (struct iw_statistics *) NULL;
 }
@@ -1843,8 +1840,33 @@ int wireless_rtnetlink_set(struct net_device *   dev,
  */
 
 #ifdef WE_EVENT_RTNETLINK
+/* ---------------------------------------------------------------- */
+/*
+ * Locking...
+ * ----------
+ *
+ * Thanks to Herbert Xu <herbert@gondor.apana.org.au> for fixing
+ * the locking issue in here and implementing this code !
+ *
+ * The issue : wireless_send_event() is often called in interrupt context,
+ * while the Netlink layer can never be called in interrupt context.
+ * The fully formed RtNetlink events are queued, and then a tasklet is run
+ * to feed those to Netlink.
+ * The skb_queue is interrupt safe, and its lock is not held while calling
+ * Netlink, so there is no possibility of dealock.
+ * Jean II
+ */
+
 static struct sk_buff_head wireless_nlevent_queue;
 
+static int __init wireless_nlevent_init(void)
+{
+       skb_queue_head_init(&wireless_nlevent_queue);
+       return 0;
+}
+
+subsys_initcall(wireless_nlevent_init);
+
 static void wireless_nlevent_process(unsigned long data)
 {
        struct sk_buff *skb;
@@ -1921,13 +1943,6 @@ static inline void rtmsg_iwinfo(struct net_device *      dev,
        tasklet_schedule(&wireless_nlevent_tasklet);
 }
 
-static int __init wireless_nlevent_init(void)
-{
-       skb_queue_head_init(&wireless_nlevent_queue);
-       return 0;
-}
-
-subsys_initcall(wireless_nlevent_init);
 #endif /* WE_EVENT_RTNETLINK */
 
 /* ---------------------------------------------------------------- */
index 75320b6842ab59e0bbd7d4d160249585ff649e39..2aa779d18f3861a2f6f2119f99c89c6c2c56b583 100644 (file)
@@ -80,10 +80,10 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
         * If it's our network, ignore the change, we're already doing it!
         */
        if((sm->associnfo.associating || sm->associated) &&
-          (data->essid.flags && data->essid.length && extra)) {
+          (data->essid.flags && data->essid.length)) {
                /* Get the associating network */
                n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid);
-               if(n && n->essid.len == (data->essid.length - 1) &&
+               if(n && n->essid.len == data->essid.length &&
                   !memcmp(n->essid.data, extra, n->essid.len)) {
                        dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n",
                                MAC_ARG(sm->associnfo.bssid));
@@ -109,8 +109,8 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev,
        sm->associnfo.static_essid = 0;
        sm->associnfo.assoc_wait = 0;
 
-       if (data->essid.flags && data->essid.length && extra /*required?*/) {
-               length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE);
+       if (data->essid.flags && data->essid.length) {
+               length = min((int)data->essid.length, IW_ESSID_MAX_SIZE);
                if (length) {
                        memcpy(sm->associnfo.req_essid.data, extra, length);
                        sm->associnfo.static_essid = 1;
index dfa504fe383f0b56d69aecc8ce5031609e16d91f..700c6e061a044fc77eee9a17db6151f58bdd2c9b 100644 (file)
@@ -488,7 +488,6 @@ rpc_get_inode(struct super_block *sb, int mode)
                return NULL;
        inode->i_mode = mode;
        inode->i_uid = inode->i_gid = 0;
-       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks = 0;
        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
        switch(mode & S_IFMT) {
@@ -858,7 +857,6 @@ int register_rpc_pipefs(void)
 
 void unregister_rpc_pipefs(void)
 {
-       if (kmem_cache_destroy(rpc_inode_cachep))
-               printk(KERN_WARNING "RPC: unable to free inode cache\n");
+       kmem_cache_destroy(rpc_inode_cachep);
        unregister_filesystem(&rpc_pipe_fs_type);
 }
index 6390461a97563852ce72558a77d3090c0e4750e0..a1ab4eed41f4b5a495f18573aef04b3457403ba3 100644 (file)
@@ -1059,10 +1059,10 @@ rpc_destroy_mempool(void)
                mempool_destroy(rpc_buffer_mempool);
        if (rpc_task_mempool)
                mempool_destroy(rpc_task_mempool);
-       if (rpc_task_slabp && kmem_cache_destroy(rpc_task_slabp))
-               printk(KERN_INFO "rpc_task: not all structures were freed\n");
-       if (rpc_buffer_slabp && kmem_cache_destroy(rpc_buffer_slabp))
-               printk(KERN_INFO "rpc_buffers: not all structures were freed\n");
+       if (rpc_task_slabp)
+               kmem_cache_destroy(rpc_task_slabp);
+       if (rpc_buffer_slabp)
+               kmem_cache_destroy(rpc_buffer_slabp);
 }
 
 int
index 3d523899fdc05dc56e5a2eb6c18e88b26390d102..4f5ff19b992b1f8a8db6f28a96cbace409db3baa 100644 (file)
@@ -63,6 +63,13 @@ as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
             -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
             else echo "$(2)"; fi ;)
 
+# as-instr
+# Usage: cflags-y += $(call as-instr, instr, option1, option2)
+
+as-instr = $(shell if echo -e "$(1)" | $(AS) >/dev/null 2>&1 -W -Z -o astest$$$$.out ; \
+                  then echo "$(2)"; else echo "$(3)"; fi; \
+                  rm -f astest$$$$.out)
+
 # cc-option
 # Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
 
diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh
new file mode 100644 (file)
index 0000000..325c0a1
--- /dev/null
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+echo "int foo(void) { char X[200]; return 3; }" | $1 -S -xc -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
+if [ "$?" -eq "0" ] ; then
+       echo $2
+fi
index de76da80443f757a8ed90ce4f27dd53e2ff2a8db..f61c9ccef6aa562889a2a8c867730c7d05de0f91 100644 (file)
@@ -444,6 +444,14 @@ static int do_input_entry(const char *filename, struct input_device_id *id,
        return 1;
 }
 
+static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa,
+               char *alias)
+{
+       if (eisa->sig[0])
+               sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", eisa->sig);
+       return 1;
+}
+
 /* Ignore any prefix, eg. v850 prepends _ */
 static inline int sym_is(const char *symbol, const char *name)
 {
@@ -547,6 +555,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
                do_table(symval, sym->st_size,
                         sizeof(struct input_device_id), "input",
                         do_input_entry, mod);
+       else if (sym_is(symname, "__mod_eisa_device_table"))
+               do_table(symval, sym->st_size,
+                        sizeof(struct eisa_device_id), "eisa",
+                        do_eisa_entry, mod);
 }
 
 /* Now add out buffered information to the generated C source */
index 47eb63480dac94ab2bd90c39a6894e38ebe71d71..49ee5152939674349e4174025b78ed2769be731a 100644 (file)
@@ -44,8 +44,8 @@ static ssize_t default_write_file(struct file *file, const char __user *buf,
 
 static int default_open(struct inode *inode, struct file *file)
 {
-       if (inode->u.generic_ip)
-               file->private_data = inode->u.generic_ip;
+       if (inode->i_private)
+               file->private_data = inode->i_private;
 
        return 0;
 }
@@ -64,7 +64,6 @@ static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
                inode->i_mode = mode;
                inode->i_uid = 0;
                inode->i_gid = 0;
-               inode->i_blksize = PAGE_CACHE_SIZE;
                inode->i_blocks = 0;
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                switch (mode & S_IFMT) {
@@ -194,7 +193,7 @@ static int create_by_name(const char *name, mode_t mode,
  *          directory dentry if set.  If this paramater is NULL, then the
  *          file will be created in the root of the securityfs filesystem.
  * @data: a pointer to something that the caller will want to get to later
- *        on.  The inode.u.generic_ip pointer will point to this value on
+ *        on.  The inode.i_private pointer will point to this value on
  *        the open() call.
  * @fops: a pointer to a struct file_operations that should be used for
  *        this file.
@@ -240,7 +239,7 @@ struct dentry *securityfs_create_file(const char *name, mode_t mode,
                if (fops)
                        dentry->d_inode->i_fop = fops;
                if (data)
-                       dentry->d_inode->u.generic_ip = data;
+                       dentry->d_inode->i_private = data;
        }
 exit:
        return dentry;
index 00534c302ba2b11939807dd5668f3530cd73fd96..bab7b386cb8dee7cd21a1fe21f9741960d34f59c 100644 (file)
@@ -771,7 +771,6 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode)
        if (ret) {
                ret->i_mode = mode;
                ret->i_uid = ret->i_gid = 0;
-               ret->i_blksize = PAGE_CACHE_SIZE;
                ret->i_blocks = 0;
                ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
        }
index 7b168d85f4ab83ea42e682fc6ff84afb48a97832..83ff8a71f716b9b4d29ce8b9e05a78b21ee74fcb 100644 (file)
@@ -1,3 +1,14 @@
+/*
+ * sound/oss/sh_dac_audio.c
+ *
+ * SH DAC based sound :(
+ *
+ *  Copyright (C) 2004,2005  Andriy Skulysh
+ *
+ * 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/module.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/sound.h>
 #include <linux/soundcard.h>
+#include <linux/interrupt.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
 #include <asm/delay.h>
-#include <linux/interrupt.h>
-
+#include <asm/clock.h>
 #include <asm/cpu/dac.h>
-
-#ifdef MACH_HP600
+#include <asm/cpu/timer.h>
+#include <asm/machvec.h>
 #include <asm/hp6xx/hp6xx.h>
-#include <asm/hd64461/hd64461.h>
-#endif
+#include <asm/hd64461.h>
 
 #define MODNAME "sh_dac_audio"
 
 #define TMU1_TCR_INIT  0x0020  /* Clock/4, rising edge; interrupt on */
 #define TMU1_TSTR_INIT  0x02   /* Bit to turn on TMU1 */
 
-#define TMU_TSTR       0xfffffe92
-#define TMU1_TCOR      0xfffffea0
-#define TMU1_TCNT      0xfffffea4
-#define TMU1_TCR       0xfffffea8
-
 #define BUFFER_SIZE 48000
 
 static int rate;
@@ -71,34 +76,37 @@ static void dac_audio_sync(void)
 
 static void dac_audio_start(void)
 {
-#ifdef MACH_HP600
-       u16 v;
-       v = inw(HD64461_GPADR);
-       v &= ~HD64461_GPADR_SPEAKER;
-       outw(v, HD64461_GPADR);
-#endif
+       if (mach_is_hp6xx()) {
+               u16 v = inw(HD64461_GPADR);
+               v &= ~HD64461_GPADR_SPEAKER;
+               outw(v, HD64461_GPADR);
+       }
+
        sh_dac_enable(CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
        ctrl_outw(TMU1_TCR_INIT, TMU1_TCR);
 }
 static void dac_audio_stop(void)
 {
-#ifdef MACH_HP600
-       u16 v;
-#endif
        dac_audio_stop_timer();
-#ifdef MACH_HP600
-       v = inw(HD64461_GPADR);
-       v |= HD64461_GPADR_SPEAKER;
-       outw(v, HD64461_GPADR);
-#endif
+
+       if (mach_is_hp6xx()) {
+               u16 v = inw(HD64461_GPADR);
+               v |= HD64461_GPADR_SPEAKER;
+               outw(v, HD64461_GPADR);
+       }
+
+       sh_dac_output(0, CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
        sh_dac_disable(CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
 }
 
 static void dac_audio_set_rate(void)
 {
        unsigned long interval;
+       struct clk *clk;
 
-       interval = (current_cpu_data.module_clock / 4) / rate;
+       clk = clk_get("module_clk");
+       interval = (clk_get_rate(clk) / 4) / rate;
+       clk_put(clk);
        ctrl_outl(interval, TMU1_TCOR);
        ctrl_outl(interval, TMU1_TCNT);
 }
index 5105b6b057484ffb0408e509e90f70a45e3d799e..abe29dadd979365e01d1458ac00531dd292d1984 100644 (file)
@@ -181,9 +181,9 @@ static int snd_usbmidi_urb_error(int status)
        case -ENODEV:
                return -ENODEV;
        /* errors that might occur during unplugging */
-       case -EPROTO:    /* EHCI */
-       case -ETIMEDOUT: /* OHCI */
-       case -EILSEQ:    /* UHCI */
+       case -EPROTO:
+       case -ETIME:
+       case -EILSEQ:
                return -EIO;
        default:
                snd_printk(KERN_ERR "urb status %d\n", status);